写的比较匆忙,功能较为单一,界面丑,操作步数应该还能优化。
最终还是要写AI,但好像没那么简单,写了几个关于格局评价的函数,还得继续学习。。。
上下左右方向键操作。
源代码:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.*;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
public class My2048 extends JFrame {
JPanel numpanel = new JPanel();
JPanel scorepanel = new JPanel();
JLabel numlabellist[][] = new JLabel[4][4];// 数字格子
int numlist[][] = new int[4][4];// 数组格子对应数值
int blanks = 16;// 空白格子数
int score=0;//总得分
JLabel scorelabel=new JLabel();
int numlist2[][] = new int[4][4];//用于格局评价时的数组
int smoothweight=1;
int monoweight=10;
int emptyweight=27;
int maxweight=10;
public static void main(String[] args) {
new My2048().launchFrame();
}
public void AddNumArea() {
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++) {
numlabellist[i][j] = new JLabel();
numlist[i][j] = 0;
numlabellist[i][j].setBackground(Color.LIGHT_GRAY);
numlabellist[i][j].setBorder(new TitledBorder(""));
numlabellist[i][j].setFont(new Font("Romantic", Font.BOLD, 35));
numlabellist[i][j].setHorizontalAlignment(JTextField.CENTER);
numpanel.add(numlabellist[i][j]);
}
}
public void AddScoreLabel(){
scorelabel.setBackground(Color.MAGENTA);
scorelabel.setFont(new Font("Romantic", Font.BOLD, 35));
scorelabel.setHorizontalAlignment(JTextField.CENTER);
scorelabel.setText("score:"+Integer.toString(score));
scorepanel.add(scorelabel);
}
// 随机选一个空白格子
public int RandomIndex(int blanks) {
Random random = new Random(System.currentTimeMillis());
int result = random.nextInt(blanks)+1;
return result;
}
// 2,4随机选一个
public int RandomValue() {
Random random = new Random();
int result = random.nextInt(2);
return (result+1)*2;
}
//空白处产生一新值,自带refresh功能
public void NewValue() {
int newvalue = RandomValue();// 新值
int index = RandomIndex(blanks);// 新值得位置
blanks--;// 空白格子数-1
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++) {
if (numlist[i][j] == 0)
index--;
if (index == 0) {
numlist[i][j] = newvalue;
// 相应label上显示新值
numlabellist[i][j].setText(Integer.toString(newvalue));
return;
}
}
}
public boolean LeftReduce() {
boolean changed=false;//是否有改变(移动和相加),作为后续是否产生新值得依据
boolean has0before;
int p;// 行指针
int value;//当前值
for (int i = 0; i < 4; i++)
{
p=0;
value=0;
has0before=false;
for (int j = 0; j < 4; j++)
{
if(numlist[i][j]>0&&has0before)//移动方向上之前有空格,可移动,changed为true
changed=true;
if(numlist[i][j]==0)
has0before=true;
if (numlist[i][j] > 0)
{
if(numlist[i][j]==value)//相加放p位置
{
int sum=value*2;
numlist[i][j]=0;
numlist[i][p]=sum;
value=0;
p++;
score+=sum;
changed=true;//相加,changed为true
}
else
{
if(value>0)//value放p中,当前值放value中
{
numlist[i][p]=value;
p++;
}
value=numlist[i][j];
numlist[i][j]=0;
}
}
}
if(value>0)//到最后value中可能有值
numlist[i][p]=value;
}
return changed;
}
public boolean RightReduce() {
boolean changed=false;//是否有改变(移动和相加),作为后续是否产生新值得依据
boolean has0before;
int p;// 行指针
int value;//当前值
for (int i = 0; i <4; i++)
{
p=3;
value=0;
has0before=false;
for (int j = 3; j >= 0; j--)
{
if(numlist[i][j]>0&&has0before)//移动方向上之前有空格,可移动,changed为true
changed=true;
if(numlist[i][j]==0)
has0before=true;
if (numlist[i][j] > 0)
{
if(numlist[i][j]==value)//相加放p位置
{
int sum=value*2;
numlist[i][j]=0;
numlist[i][p]=sum;
value=0;
p--;
score+=sum;
changed=true;//相加,changed为true
}
else
{
if(value>0)//value放p中,当前值放value中
{
numlist[i][p]=value;
p--;
}
value=numlist[i][j];
numlist[i][j]=0;
}
}
}
if(value>0)//到最后value中可能有值
numlist[i][p]=value;
}
return changed;
}
public boolean UpReduce() {
boolean changed=false;//是否有改变(移动和相加),作为后续是否产生新值得依据
boolean has0before;
int p;// 行指针
int value;//当前值
for (int j = 0; j <4; j++)
{
p=0;
value=0;
has0before=false;
for (int i = 0; i <4; i++)
{
if(numlist[i][j]>0&&has0before)//移动方向上之前有空格,可移动,changed为true
changed=true;
if(numlist[i][j]==0)
has0before=true;
if (numlist[i][j] > 0)
{
if(numlist[i][j]==value)//相加放p位置
{
int sum=value*2;
numlist[i][j]=0;
numlist[p][j]=sum;
value=0;
p++;
score+=sum;
changed=true;//相加,changed为true
}
else
{
if(value>0)//value放p中,当前值放value中
{
numlist[p][j]=value;
p++;
}
value=numlist[i][j];
numlist[i][j]=0;
}
}
}
if(value>0)//到最后value中可能有值
numlist[p][j]=value;
}
return changed;
}
public boolean DownReduce() {
boolean changed=false;//是否有改变(移动和相加),作为后续是否产生新值得依据
boolean has0before;
int p;// 行指针
int value;//当前值
for (int j = 0; j <4; j++)
{
p=3;
value=0;
has0before=false;
for (int i = 3; i >=0; i--)
{
if(numlist[i][j]>0&&has0before)//移动方向上之前有空格,可移动,changed为true
changed=true;
if(numlist[i][j]==0)
has0before=true;
if (numlist[i][j] > 0)
{
if(numlist[i][j]==value)//相加放p位置
{
int sum=value*2;
numlist[i][j]=0;
numlist[p][j]=sum;
value=0;
p--;
score+=sum;
changed=true;//相加,changed为true
}
else
{
if(value>0)//value放p中,当前值放value中
{
numlist[p][j]=value;
p--;
}
value=numlist[i][j];
numlist[i][j]=0;
}
}
}
if(value>0)//到最后value中可能有值
numlist[p][j]=value;
}
return changed;
}
public void Refresh(){
blanks=0;
scorelabel.setText("score:"+Integer.toString(score));
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
{
if(numlist[i][j]!=0)
numlabellist[i][j].setText(Integer.toString(numlist[i][j]));
else
{
numlabellist[i][j].setText(null);
blanks++;
}
}
}
public boolean CheckOut(){
if(blanks>0)
return false;
for(int i=0;i<4;i++)
for(int j=0;j<3;j++)
{
if(numlist[i][j]==numlist[i][j+1])
return false;
}
for(int j=0;j<4;j++)
for(int i=0;i<3;i++)
{
if(numlist[i][j]==numlist[i+1][j])
return false;
}
return true;
}
public void Out(){
JOptionPane.showMessageDialog(null, "游戏结束!", "2048PC版", 2);
System.exit(0);
}
public void PrintNumlist() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++)
{
System.out.print(numlist[i][j]);
System.out.print(' ');
}
System.out.println();
}
System.out.println("***********************");
}
//单调率,后期乘以monoweight(干脆方法内乘了)
public int Mononess(){
int result1=0;//从右往左递增度量
int result2=0;//从上往下递增度量
int lastvalue=0;
for(int i=0;i<4;i++)
{
lastvalue=0;
for(int j=0;j<4;j++)
{
if(numlist[i][j]>0)
{
if(lastvalue>0)
if(numlist[i][j]<lastvalue)
result1++;
if(numlist[i][j]>lastvalue)
result1--;
lastvalue=numlist[i][j];
}
}
}
lastvalue=0;
for(int j=0;j<4;j++)
{
lastvalue=0;
for(int i=0;i<4;i++)
{
if(numlist[i][j]>0)
{
if(lastvalue>0)
if(numlist[i][j]>lastvalue)
result2++;
if(numlist[i][j]<lastvalue)
result2--;
lastvalue=numlist[i][j];
}
}
}
if(result2>result1)
return result2*monoweight;
return result1*monoweight;
}
//平滑率,是负数,是差的和的相反数,后期乘以smoothweight(干脆方法内乘了)
public int Smoothness(){
int result1=0;//水平方向
int result2=0;//竖直方向
int lastvalue=0;
for(int i=0;i<4;i++)
{
lastvalue=0;
for(int j=0;j<4;j++)
{
if(numlist[i][j]>0)
{
if(lastvalue>0)
result1+=Math.abs(numlist[i][j]-lastvalue);
lastvalue=numlist[i][j];
}
}
}
lastvalue=0;
for(int j=0;j<4;j++)
{
lastvalue=0;
for(int i=0;i<4;i++)
{
if(numlist[i][j]>0)
{
if(lastvalue>0)
result2+=Math.abs(numlist[i][j]-lastvalue);
lastvalue=numlist[i][j];
}
}
}
if(result2>result1)
return (0-result1)*smoothweight;
return (0-result2)*smoothweight;
}
//最大数,后期乘以maxweight(干脆方法内乘了)
public int Maxness(){
int max=0;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(numlist[i][j]>max)
max=numlist[i][j];
return max*maxweight;
}
public int Emptyness(){
return blanks*emptyweight;
}
public void launchFrame() {
setTitle("2048PC版"); // 设置窗体标题
setBounds(700, 100, 400, 475);
setLayout(new BorderLayout());
setResizable(false); // 禁止调整窗体大小
numpanel.setLayout(new GridLayout(4, 4)); // 设置空布局
numpanel.setLocation(0,200);
AddScoreLabel();//添加计分器
AddNumArea();// 添加数字格子
getContentPane().add(scorepanel,BorderLayout.NORTH);
getContentPane().add(numpanel,BorderLayout.CENTER);
NewValue();
NewValue();
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
this.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 37)// 左键
{
if(LeftReduce())
{
Refresh();//更新blank,numlabellist
NewValue();
} }
if (e.getKeyCode() == 39)// 右键
{
if(RightReduce())
{
Refresh();//更新blank,numlabellist
NewValue();
} }
if (e.getKeyCode() == 38)// 上键
{
if(UpReduce())
{
Refresh();//更新blank,numlabellist
NewValue();
} }
if (e.getKeyCode() == 40)// 上键
{
if(DownReduce())
{
Refresh();//更新blanks,numlabellist,scorelabel
NewValue();
}
}
if (e.getKeyCode() == 32)// 空格键
{
if(LeftReduce())
{
Refresh();//更新blanks,numlabellist,scorelabel
NewValue();
}
else if(RightReduce())
{
Refresh();//更新blanks,numlabellist,scorelabel
NewValue();
}
else if(UpReduce())
{
Refresh();//更新blanks,numlabellist,scorelabel
NewValue();
}
else if(DownReduce())
{
Refresh();//更新blanks,numlabellist,scorelabel
NewValue();
}
}
System.out.println(e.getKeyCode());
if(CheckOut())//检查游戏是否结束
Out();
PrintNumlist();
System.out.println("mononess:"+Integer.toString(Mononess()));
System.out.println("smoothness:"+Integer.toString(Smoothness()));
System.out.println("maxnum:"+Integer.toString(Maxness()));
System.out.println("blanks:"+Integer.toString(Emptyness()));
}
});
setVisible(true);
}
}