五子棋人机对战实践项目

总的任务和目标

完成一个人机对战的五子棋项目,基本效果如下:

第一部分 Java绘图原理

1.   基本概念

像素,坐标

第二部分 绘制棋盘

1.   基本思路

在一个JPanel上绘制一个背景,然后绘制水平和垂直的若干条线,使其构成等距离的格子,通常是15*15(条线)。

2.   代码实现

第三部分 绘制棋子

1.   基本思路

使用drawOval()可以绘制空心的圆,使用fillOval()可以填充实心的圆。

2.   坐标计算

由于格子是水平和垂直的有下标的,而绘制时需要使用实际的像素坐标,所以,需要进行行列下标到像素坐标的转换:

int x = col * GRID_WIDTH;

int y = row * GRID_WIDTH;

3.   代码实现

(1)     ChessPanel代码:

第四部分 鼠标下棋

1.   基本思路

需要处理鼠标单点事件,获取鼠标所在的位置,然后计算出应该绘制棋子的行列下标,并使用一个二维数组来全局存储棋子的位置。

2.   鼠标位置与行列下标计算

int x = e.getX();

int y = e.getY();

int row = y / GRID_WIDTH;

 int col = x / GRID_WIDTH;

3.   代码实现

(1)      ChessPanel属性和构造方法代码:

(2)监听器类(内部类)代码:

(3)绘图代码:

第五部分 判断胜负

1.   基本思路

判断胜负是因为在当前位置(row, col)落子导致了胜负,所以,判断胜负其实是在当前落子位置为中心,横向搜索左边第4个位置开始到右边第4个位置(其余位置不需要考虑),或者从上到下,或者正向45度,或者反向45度位置。

2.   处理方法

处理方法有很多,可以采用计数的方式,也可以采用字符串连接的方式,此处采用了将从左边第4颗开始,到右边第4颗结束,将每颗的颜色表示成字符1(黑色)或者2(白色),只需要判断其中是否有连续的5个1或5个2,即“11111”或“22222”即可知道胜负。

3.   代码实现

(1)     监听器类(内部类)代码:

(2)checkWin判断胜负的代码:

/** 判断胜负

* @param row      落子的行下标

* @param col       落子的列下标

* @return 是否获胜,true-是,false-否

*/

public boolean checkWin(int row, int col) {}

(3)重置游戏状态

【目前代码】

  1. package wuziqi;
  2.  
  3. import java.awt.Color;
  4. import java.awt.Container;
  5. import java.awt.Graphics;
  6. import java.awt.event.MouseAdapter;
  7. import java.awt.event.MouseEvent;
  8.  
  9. import javax.swing.JFrame;
  10. import javax.swing.JOptionPane;
  11. import javax.swing.JPanel;
  12.  
  13. public class wuziqijiemianDemo {
  14. //创建窗口为主类的类部类并且继承自JFrame
  15. public class Myjframe extends JFrame {
  16. /**
  17. * 用一个构造方法创建窗口
  18. */
  19. public Myjframe() {
  20. this.setTitle("五子棋");
  21. this.setSize(620, 640);
  22. //获取内容面板
  23. Container cp = getContentPane();
  24. //创建一个面板JPanel
  25. JPanel jPanel = new MyJanel();
  26. cp.add(jPanel);
  27. //面板的背景颜色为黄色,便于下白棋与黑棋
  28. jPanel.setBackground(Color.yellow);
  29. this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  30. //窗口默认设置为显示屏的正中间
  31. this.setLocationRelativeTo(null);
  32. //不可改变窗口的大小
  33. this.setResizable(false);
  34. }
  35. }
  36. /**
  37. * 创建一个面板继承自JPanel
  38. * @author Administrator
  39. *
  40. */
  41. public class MyJanel extends JPanel {
  42. //表示每个方格的大小
  43. private static final int GRID_WIDTh = 40;
  44. //棋盘的大小,代表棋盘的线的条数
  45. private static final int LINE_COUNT = 15;
  46. //设置黑棋子为1、白棋子为2、没有棋子为0(默认值)
  47. public static final int BLACK=1;
  48. public static final int WHITE=2;
  49. //定义一个棋盘大小的数组用来存放黑棋和白棋的位置
  50. int[][] chessItems=new int[LINE_COUNT][LINE_COUNT];
  51. //定义一个标志位,代表黑棋先下(黑棋和白棋轮流下棋)
  52. int flag=BLACK;
  53. /**
  54. * 构造方法用来画棋盘的棋子
  55. */
  56. public MyJanel(){
  57. /**
  58. * 为这个面板添加一个鼠标点击事件,鼠标每点击一次,就在棋盘上下一个棋子
  59. *使用适配器的方式添加鼠标点击事件
  60. */
  61. this.addMouseListener(new MouseAdapter() {
  62. public void mouseClicked(MouseEvent e){
  63. /**
  64. * 获取当前的鼠标点击的位置
  65. */
  66. int x=e.getX();
  67. int y=e.getY();
  68. /**
  69. * 因为棋盘是用二维数组的方式表示的,所以最后表示为二维数组的行与列
  70. */
  71. int row=y/GRID_WIDTh;
  72. int col=x/GRID_WIDTh;
  73. //当前这个位置没有棋子(为零),可以下一个黑棋子
  74. if(chessItems[row][col]==0){
  75. if(flag==BLACK){
  76. chessItems[row][col]=flag;
  77. //下完黑棋下白棋
  78. flag=WHITE;
  79. //必须有,不然后面的白棋会覆盖黑棋
  80. }
  81. //当前这个位置没有棋子(为零),可以下一个白棋子
  82. else{
  83. chessItems[row][col]=flag;
  84. //下完白棋下黑棋
  85. flag=BLACK;
  86. }
  87. }
  88. /**
  89. * 每当下完一步棋之后便判断是否已经取胜
  90. */
  91. if(checkImage(row,col)){
  92. //显示对话窗口
  93. JOptionPane.showMessageDialog(null, "your win");
  94. //清空棋盘
  95. clear();
  96. }
  97. //System.out.println(chessItems[row][col]);
  98. }
  99. });
  100. }
  101. /**
  102. * 调用public void paintComponent(Graphics arg0){};方法画图
  103. */
  104. public void paintComponent(Graphics g) {
  105. //系统调用
  106. super.paintComponent(g);
  107. // g.setColor(Color.yellow);
  108. // g.fillRect(0, 0, jPanel.width(),jPanel.height());
  109. /**
  110. * 画横线,起始位置在窗口左上定点(GRID_WIDTh/2,GRID_WIDTh/2)
  111. */
  112. for (int i = 0; i < LINE_COUNT; i++) {
  113. int x1 = GRID_WIDTh / 2;
  114. int y1 = GRID_WIDTh / 2 + i * GRID_WIDTh;
  115. int x2 = x1 + (LINE_COUNT-1)* GRID_WIDTh;
  116. int y2 = y1;
  117. //画线
  118. g.drawLine(x1, y1, x2, y2);
  119. }
  120. /**
  121. * 画竖线
  122. */
  123. for (int i = 0; i < LINE_COUNT; i++) {
  124. int x1 = GRID_WIDTh / 2 + i * GRID_WIDTh;
  125. int y1 = GRID_WIDTh / 2;
  126. int x2 = x1;
  127. int y2 = y1 + (LINE_COUNT-1) * GRID_WIDTh;
  128. //画线
  129. g.drawLine(x1, y1, x2, y2);
  130. }
  131. /**
  132. * 遍历这个数组
  133. */
  134. for(int row=0;row<LINE_COUNT;row++){
  135. for(int col=0;col<LINE_COUNT;col++){
  136. //判断数组当前值,来画棋子
  137. switch (chessItems[row][col]) {
  138. case WHITE:chessItem(row, col, Color.WHITE, g);break;
  139. case BLACK:chessItem(row, col, Color.BLACK, g);break;
  140. }
  141. repaint();
  142. }
  143. }
  144. };
  145. /**
  146. * 清空数组,便于下次下棋
  147. */
  148. private void clear() {
  149. for(int row=0;row<LINE_COUNT;row++){
  150. for(int col=0;col<LINE_COUNT;col++){
  151. //全部置为0
  152. chessItems[row][col]=0;
  153. }
  154. }
  155. //重画一遍棋盘
  156. repaint();
  157. }
  158. /**
  159. * 用于判断是否已经取胜
  160. * @param row
  161. * @param col
  162. * @return
  163. */
  164. private boolean checkImage(int row, int col) {
  165. /**
  166. * 判断横行是否win
  167. */
  168. StringBuilder stringBuilder=new StringBuilder();
  169. //记录当前存在字符串中的数据个数
  170. int count=0;
  171. for(int i=-4;i<=4;i++){
  172. int Newcol=col+i;
  173. if(Newcol>=0&&Newcol<LINE_COUNT){
  174. count++;
  175. stringBuilder.append(chessItems[row][Newcol]);
  176. }
  177. }
  178. if(stringBuilder.indexOf("11111")>=0||stringBuilder.indexOf("22222")>=0){
  179. return true;
  180. }else {
  181. //如果当前不能赢,则清空字符串
  182. stringBuilder.delete(0, count);
  183. count=0;
  184. }
  185. /**
  186. * 判断竖行是否win
  187. */
  188. for(int i=-4;i<=4;i++){
  189. int Newrow=row+i;
  190. if(Newrow>=0&&Newrow<LINE_COUNT){
  191. count++;
  192. stringBuilder.append(chessItems[Newrow][col]);
  193. }
  194. }
  195. if(stringBuilder.indexOf("11111")>=0||stringBuilder.indexOf("22222")>=0){
  196. return true;
  197. }else {
  198. stringBuilder.delete(0, count);
  199. count=0;
  200. }
  201. /**
  202. * 判断负45°是否win
  203. */
  204. for(int i=-4;i<=4;i++){
  205. int Newcol=col+i;
  206. int Newrow=row+i;
  207. if(Newcol>=0&&Newcol<LINE_COUNT&&Newrow>=0&&Newrow<LINE_COUNT){
  208. count++;
  209. stringBuilder.append(chessItems[Newrow][Newcol]);
  210. }
  211. }
  212. if(stringBuilder.indexOf("11111")>=0||stringBuilder.indexOf("22222")>=0){
  213. return true;
  214. }else {
  215. stringBuilder.delete(0, count);
  216. count=0;
  217. }
  218. /**
  219. * 判断正45°是否win
  220. */
  221. for(int i=-4;i<=4;i++){
  222. int Newcol=col+i;
  223. int Newrow=row-i;
  224. if(Newcol>=0&&Newcol<LINE_COUNT&&Newrow>=0&&Newrow<LINE_COUNT){
  225. count++;
  226. stringBuilder.append(chessItems[Newrow][Newcol]);
  227. }
  228. }
  229. if(stringBuilder.indexOf("11111")>=0||stringBuilder.indexOf("22222")>=0){
  230. return true;
  231. }else {
  232. stringBuilder.delete(0, count);
  233. count=0;
  234. }
  235. return false;
  236. }
  237. //画棋子
  238. public void chessItem(int row,int col,Color color,Graphics graphics){
  239. //x与y分别代表在面板上的位置
  240. int x=col*GRID_WIDTh;
  241. int y=row*GRID_WIDTh;
  242. graphics.setColor(color);
  243. //画圆
  244. graphics.fillOval(x, y, GRID_WIDTh,GRID_WIDTh);
  245. }
  246. }
  247.  
  248. public static void main(String[] args) {
  249. /**
  250. * 使用一个java类来创建一个主类为wuziqijiemianDemo,其中的窗口与棋盘为该主类的内部类
  251. */
  252. //使用类部类的方式创建一个窗口引用对象(方式为 外部类名.内部类名 变量名=new 外部类名().new 内部类名();)
  253. wuziqijiemianDemo.Myjframe myjframe = new wuziqijiemianDemo().new Myjframe();
  254. //设置窗口可见
  255. myjframe.setVisible(true);
  256. }
  257.  
  258. }

第六部分 人机对战

1.   基本思路

当人点了鼠标落子以后,轮到电脑下棋,电脑的基本思想就是,在棋盘的空白处的每个位置,进行判断,当前位置的进攻指数和防守指数分别为多少,在进攻指数和防守指数中取一个较大值作为当前位置的评估值,在整个棋盘的所有空白处找到一个最大值,最大值的那个位置即为应该落子的位置。

2.  代码实现

(1)监听器类(内部类)代码:

(2)电脑下棋的代码

(3)     评估关键参数代码:

(4) 评估方法代码:

【自己代码】

  1. package wuziqi;
  2.  
  3. import java.awt.Color;
  4. import java.awt.Container;
  5. import java.awt.Graphics;
  6. import java.awt.Image;
  7. import java.awt.Point;
  8. import java.awt.event.MouseAdapter;
  9. import java.awt.event.MouseEvent;
  10. import java.io.File;
  11. import java.io.IOException;
  12.  
  13. import javax.imageio.ImageIO;
  14. import javax.swing.JFrame;
  15. import javax.swing.JOptionPane;
  16. import javax.swing.JPanel;
  17.  
  18. public class wuziqijiemianDemo {
  19. // 创建窗口为主类的类部类并且继承自JFrame
  20. public class Myjframe extends JFrame {
  21. /**
  22. * 用一个构造方法创建窗口
  23. */
  24. public Myjframe() {
  25. this.setTitle("五子棋");
  26. this.setSize(620, 640);
  27. // 获取内容面板
  28. Container cp = getContentPane();
  29. // 创建一个面板JPanel
  30. JPanel jPanel = new MyJanel();
  31. cp.add(jPanel);
  32. // 面板的背景颜色为黄色,便于下白棋与黑棋
  33. jPanel.setBackground(Color.yellow);
  34. this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
  35. // 窗口默认设置为显示屏的正中间
  36. this.setLocationRelativeTo(null);
  37. // 不可改变窗口的大小
  38. this.setResizable(false);
  39. }
  40. }
  41.  
  42. /**
  43. * 创建一个面板继承自JPanel
  44. *
  45. * @author Administrator
  46. *
  47. */
  48. public class MyJanel extends JPanel {
  49. // 表示每个方格的大小
  50. private static final int GRID_WIDTh = 40;
  51. // 棋盘的大小,代表棋盘的线的条数
  52. private static final int LINE_COUNT = 15;
  53. // 设置黑棋子为1、白棋子为2、没有棋子为0(默认值)
  54. public static final int BLACK = 1;
  55. public static final int WHITE = 2;
  56. // 定义一个棋盘大小的数组用来存放黑棋和白棋的位置
  57. int[][] chessItems = new int[LINE_COUNT][LINE_COUNT];
  58. // 定义一个标志位,代表黑棋先下(黑棋和白棋轮流下棋)
  59. int flag = BLACK;
  60. //定义一个方框标记计算机下棋的棋子
  61. private Point lastpoint=new Point();
  62. //利用图片代表棋子
  63. Image blackImage=null;
  64. Image whiImage=null;
  65. //定义一个进攻的数组
  66. String[] defendstring={
  67. "11111","011110","11110","01111","11011",
  68. "10111","11101","01110","11100","00111",
  69. "0111","1110","1011","1101","111",
  70. "01100","00110","011","110","11"
  71. };
  72. //定义一个防守的数组
  73. String[] attackstring={
  74. "22222","022220","22220","02222","22022",
  75. "20222","22202","02220","22200","00222",
  76. "0222","2220","2022","2202","222",
  77. "02200","00220","022","220","22"
  78. };
  79. //定义一个防守与进攻对应的得分
  80. int[] score={
  81. 100,90,80,80,80,
  82. 80,80,70,60,60,
  83. 50,50,50,50,40,
  84. 30,30,20,20,10,
  85. };
  86. /**
  87. * 构造方法用来画棋盘的棋子
  88. */
  89. public MyJanel() {
  90. /**
  91. * 将棋子改变为图片,将黑子白子图片导入进来
  92. */
  93. try {
  94. blackImage=ImageIO.read(new File("imgs/black.png"));
  95. whiImage=ImageIO.read(new File("imgs/WHITE.png"));
  96. } catch (IOException e1) {
  97. // TODO Auto-generated catch block
  98. e1.printStackTrace();
  99. }
  100. /**
  101. * 为这个面板添加一个鼠标点击事件,鼠标每点击一次,就在棋盘上下一个棋子 使用适配器的方式添加鼠标点击事件
  102. */
  103. this.addMouseListener(new MouseAdapter() {
  104. public void mouseClicked(MouseEvent e) {
  105. /**
  106. * 获取当前的鼠标点击的位置
  107. */
  108. int x = e.getX();
  109. int y = e.getY();
  110. /**
  111. * 因为棋盘是用二维数组的方式表示的,所以最后表示为二维数组的行与列
  112. */
  113. int row = y / GRID_WIDTh;
  114. int col = x / GRID_WIDTh;
  115. // 当前这个位置没有棋子(为零),可以下一个黑棋子
  116. if (chessItems[row][col] == 0) {
  117. //人先下黑棋
  118. chessItems[row][col] = flag;
  119. /**
  120. * 每当下完一步棋之后便判断是否已经取胜
  121. */
  122. if (checkImage(row, col)) {
  123. JOptionPane.showMessageDialog(null, "你赢了");
  124. clear();
  125. return;
  126. }
  127. // 人下完黑棋下白棋,之后再给计算机下黑棋的机会
  128. flag = WHITE;
  129. //计算机下棋
  130. computerPlay();
  131. // 计算机下完摆起之后,给人下黑棋的机会
  132. flag = BLACK;
  133. // 必须有,不然后面的白棋会覆盖黑棋
  134. }
  135. // System.out.println(chessItems[row][col]);
  136. }
  137. //计算机下棋调用方法
  138. private void computerPlay() {
  139. // 当前初始化找到的位置和期望值
  140. int tempRow = -1, tempCol = -1, maxValue = 0;
  141. // 遍历数组一个位置一个位置的找
  142. for (int i = 0; i < LINE_COUNT; i++) {
  143. for (int j = 0; j < LINE_COUNT; j++) {
  144. // 如果这个位置已经下棋,则跳过
  145. if (chessItems[i][j] > 0) {
  146. continue;
  147. }
  148. // 表示进攻得分和防守得分
  149. int attack = CheckMax(i, j, WHITE);
  150. int defend= CheckMax(i, j, BLACK);
  151. int max = Math.max(attack, defend);
  152. // 获取最大值,并记录下标
  153. if (max > maxValue) {
  154. tempRow = i;
  155. tempCol = j;
  156. maxValue = max;
  157. }
  158. }
  159. }
  160. //如果当前计算机没有找到下棋的位置,表明为平局
  161. if(tempCol<0||tempRow<0){
  162. JOptionPane.showMessageDialog(null, "平局");
  163. clear();
  164. return;
  165. }else{
  166. // 计算机下白棋,下完之后人下黑棋,画一遍
  167. chessItems[tempRow][tempCol] = WHITE;
  168. lastpoint.x=tempRow;
  169. lastpoint.y=tempCol;
  170. repaint();
  171. }
  172. // 计算机下完棋之后便判断自己是否已经获胜
  173. if (checkImage(tempRow, tempCol)) {
  174. JOptionPane.showMessageDialog(null, "你输了");
  175. clear();
  176. return;
  177. }
  178. }
  179. //计算机查看当前位置(黑棋与白棋)
  180. private int CheckMax(int row, int col, int current_colorpointer) {
  181. //max记录最大的期望,而tempmax记录当前的期望
  182. int max=0,tempmax=0;
  183. //判断当前是进攻还是防守
  184. String[] array=current_colorpointer==WHITE?attackstring:defendstring;
  185. //用一个字符串存放当前的状态
  186. StringBuilder stringBuilder=new StringBuilder();
  187. //水平方向
  188. for (int i = -4; i <= 4; i++) {
  189. int Newcol = col + i;
  190. if (Newcol<0 ||Newcol >= LINE_COUNT) {
  191. continue;
  192. }
  193. //假装先把这个位置下棋,实质上并没有下棋
  194. if(i==0){
  195. stringBuilder.append(current_colorpointer);
  196. }else{
  197. stringBuilder.append(chessItems[row][Newcol]);
  198. }
  199. }
  200. for(int i=0;i<array.length;i++){
  201. String string=array[i];
  202. //查找匹配字符串数组,并计算出期望值,找到即跳出循环
  203. if(stringBuilder.indexOf(string)>=0){
  204. max=score[i];
  205. break;
  206. }
  207. }
  208. //如果当前为最大的期望,即可以获胜,就直接return
  209. if(max==100){
  210. return max;
  211. }
  212. //每次在每个方向判断之后,应该清空当前的stringBuilder字符串
  213. stringBuilder.delete(0, stringBuilder.length());
  214. //垂直方向
  215. for (int i = -4; i <= 4; i++) {
  216. int Newrow = row + i;
  217. if (Newrow<0 ||Newrow >= LINE_COUNT) {
  218. continue;
  219. }
  220. if(i==0){
  221. stringBuilder.append(current_colorpointer);
  222. }else{
  223. stringBuilder.append(chessItems[Newrow][col]);
  224. }
  225. }
  226. tempmax=0;
  227. for(int i=0;i<array.length;i++){
  228. String string=array[i];
  229. if(stringBuilder.indexOf(string)>=0){
  230. tempmax=score[i];
  231. break;
  232. }
  233. }
  234. if(max<tempmax){
  235. max=tempmax;
  236. }
  237. if(max==100){
  238. return max;
  239. }
  240. //每次在每个方向判断之后,应该清空当前的stringBuilder字符串
  241. stringBuilder.delete(0, stringBuilder.length());
  242. //负45°
  243. for (int i = -4; i <= 4; i++) {
  244. int Newrow = row + i;
  245. int Newcol = col + i;
  246. if ((Newrow<0 ||Newrow >= LINE_COUNT||Newcol<0 ||Newcol >= LINE_COUNT)) {
  247. continue;
  248. }
  249. if(i==0){
  250. stringBuilder.append(current_colorpointer);
  251. }else{
  252. stringBuilder.append(chessItems[Newrow][Newcol]);
  253. }
  254. }
  255. tempmax=0;
  256. for(int i=0;i<array.length;i++){
  257. String string=array[i];
  258. if(stringBuilder.indexOf(string)>=0){
  259. tempmax=score[i];
  260. break;
  261. }
  262. }
  263. if(max<tempmax){
  264. max=tempmax;
  265. }
  266. if(max==100){
  267. return max;
  268. }
  269. //每次在每个方向判断之后,应该清空当前的stringBuilder字符串
  270. stringBuilder.delete(0, stringBuilder.length());
  271. //正45°
  272. for (int i = -4; i <= 4; i++) {
  273. int Newrow = row + i;
  274. int Newcol = col - i;
  275. if ((Newrow<0 ||Newrow >= LINE_COUNT||Newcol<0 ||Newcol >= LINE_COUNT)) {
  276. continue;
  277. }
  278. if(i==0){
  279. stringBuilder.append(current_colorpointer);
  280. }else{
  281. stringBuilder.append(chessItems[Newrow][Newcol]);
  282. }
  283. }
  284. tempmax=0;
  285. for(int i=0;i<array.length;i++){
  286. String string=array[i];
  287. if(stringBuilder.indexOf(string)>=0){
  288. tempmax=score[i];
  289. break;
  290. }
  291. }
  292. if(max<tempmax){
  293. max=tempmax;
  294. }
  295. if(max==100){
  296. return max;
  297. }
  298. return max;
  299. }
  300. });
  301. }
  302.  
  303. /**
  304. * 调用public void paintComponent(Graphics arg0){};方法画图
  305. */
  306. public void paintComponent(Graphics g) {
  307. // 系统调用
  308. super.paintComponent(g);
  309. // g.setColor(Color.yellow);
  310. // g.fillRect(0, 0, jPanel.width(),jPanel.height());
  311. /**
  312. * 画横线,起始位置在窗口左上定点(GRID_WIDTh/2,GRID_WIDTh/2)
  313. */
  314. for (int i = 0; i < LINE_COUNT; i++) {
  315. int x1 = GRID_WIDTh / 2;
  316. int y1 = GRID_WIDTh / 2 + i * GRID_WIDTh;
  317. int x2 = x1 + (LINE_COUNT - 1) * GRID_WIDTh;
  318. int y2 = y1;
  319. // 画线
  320. g.drawLine(x1, y1, x2, y2);
  321. }
  322. /**
  323. * 画竖线
  324. */
  325. for (int i = 0; i < LINE_COUNT; i++) {
  326. int x1 = GRID_WIDTh / 2 + i * GRID_WIDTh;
  327. int y1 = GRID_WIDTh / 2;
  328. int x2 = x1;
  329. int y2 = y1 + (LINE_COUNT - 1) * GRID_WIDTh;
  330. // 画线
  331. g.drawLine(x1, y1, x2, y2);
  332. }
  333. /**
  334. * 遍历这个数组
  335. */
  336. for (int row = 0; row < LINE_COUNT; row++) {
  337. for (int col = 0; col < LINE_COUNT; col++) {
  338. // 判断数组当前值,来画棋子
  339. switch (chessItems[row][col]) {
  340. case WHITE:
  341. chessItem(row, col, Color.WHITE, g);
  342. //每次画完计算机下完白棋之后,在白棋上面画一个方框
  343. chessface(lastpoint,Color.RED, g);
  344. break;
  345. case BLACK:
  346. chessItem(row, col, Color.BLACK, g);
  347. break;
  348. }
  349. repaint();
  350. }
  351. }
  352. };
  353.  
  354. /**
  355. * 清空数组,便于下次下棋
  356. */
  357. private void clear() {
  358. for (int row = 0; row < LINE_COUNT; row++) {
  359. for (int col = 0; col < LINE_COUNT; col++) {
  360. // 全部置为0
  361. chessItems[row][col] = 0;
  362. }
  363. }
  364. // 重画一遍棋盘
  365. repaint();
  366. }
  367.  
  368. /**
  369. * 用于判断是否已经取胜
  370. *
  371. * @param row
  372. * @param col
  373. * @return
  374. */
  375. private boolean checkImage(int row, int col) {
  376. /**
  377. * 判断横行是否win
  378. */
  379. StringBuilder stringBuilder = new StringBuilder();
  380. // 记录当前存在字符串中的数据个数
  381. int count = 0;
  382. for (int i = -4; i <= 4; i++) {
  383. int Newcol = col + i;
  384. if (Newcol >= 0 && Newcol < LINE_COUNT) {
  385. count++;
  386. stringBuilder.append(chessItems[row][Newcol]);
  387. }
  388. }
  389. if (stringBuilder.indexOf("11111") >= 0
  390. || stringBuilder.indexOf("22222") >= 0) {
  391. return true;
  392. } else {
  393. // 如果当前不能赢,则清空字符串
  394. stringBuilder.delete(0, count);
  395. count = 0;
  396. }
  397. /**
  398. * 判断竖行是否win
  399. */
  400. for (int i = -4; i <= 4; i++) {
  401. int Newrow = row + i;
  402. if (Newrow >= 0 && Newrow < LINE_COUNT) {
  403. count++;
  404. stringBuilder.append(chessItems[Newrow][col]);
  405. }
  406. }
  407. if (stringBuilder.indexOf("11111") >= 0
  408. || stringBuilder.indexOf("22222") >= 0) {
  409. return true;
  410. } else {
  411. stringBuilder.delete(0, count);
  412. count = 0;
  413. }
  414. /**
  415. * 判断负45°是否win
  416. */
  417. for (int i = -4; i <= 4; i++) {
  418. int Newcol = col + i;
  419. int Newrow = row + i;
  420. if (Newcol >= 0 && Newcol < LINE_COUNT && Newrow >= 0
  421. && Newrow < LINE_COUNT) {
  422. count++;
  423. stringBuilder.append(chessItems[Newrow][Newcol]);
  424. }
  425. }
  426. if (stringBuilder.indexOf("11111") >= 0
  427. || stringBuilder.indexOf("22222") >= 0) {
  428. return true;
  429. } else {
  430. stringBuilder.delete(0, count);
  431. count = 0;
  432. }
  433. /**
  434. * 判断正45°是否win
  435. */
  436. for (int i = -4; i <= 4; i++) {
  437. int Newcol = col + i;
  438. int Newrow = row - i;
  439. if (Newcol >= 0 && Newcol < LINE_COUNT && Newrow >= 0
  440. && Newrow < LINE_COUNT) {
  441. count++;
  442. stringBuilder.append(chessItems[Newrow][Newcol]);
  443. }
  444. }
  445. if (stringBuilder.indexOf("11111") >= 0
  446. || stringBuilder.indexOf("22222") >= 0) {
  447. return true;
  448. } else {
  449. stringBuilder.delete(0, count);
  450. count = 0;
  451. }
  452. return false;
  453. }
  454.  
  455. // 画棋子
  456. public void chessItem(int row, int col, Color color, Graphics graphics) {
  457. // x与y分别代表在面板上的位置
  458. int x = col * GRID_WIDTh;
  459. int y = row * GRID_WIDTh;
  460. //判断是白棋还是黑棋
  461. Image image=Color.BLACK.equals(color)?blackImage:whiImage;
  462. graphics.drawImage(image, x, y, GRID_WIDTh, GRID_WIDTh, this);
  463. // graphics.setColor(color);
  464. // // 画圆
  465. // graphics.fillOval(x, y, GRID_WIDTh, GRID_WIDTh);
  466. }
  467. /**
  468. * 为计算机画白棋定义一个方法,用于在计算机下白棋的棋子上画一个方框,表示是当前的棋子
  469. * @param point
  470. * @param color
  471. * @param graphics
  472. */
  473. public void chessface(Point point, Color color, Graphics graphics ){
  474. int x = point.y * GRID_WIDTh;
  475. int y = point.x * GRID_WIDTh;
  476. graphics.setColor(color);
  477. graphics.drawRect(x+GRID_WIDTh/4, y+GRID_WIDTh/4, GRID_WIDTh/2, GRID_WIDTh/2);
  478. }
  479. }
  480.  
  481. public static void main(String[] args) {
  482. /**
  483. * 使用一个java类来创建一个主类为wuziqijiemianDemo,其中的窗口与棋盘为该主类的内部类
  484. */
  485. // 使用类部类的方式创建一个窗口引用对象(方式为 外部类名.内部类名 变量名=new 外部类名().new 内部类名();)
  486. wuziqijiemianDemo.Myjframe myjframe = new wuziqijiemianDemo().new Myjframe();
  487. // 设置窗口可见
  488. myjframe.setVisible(true);
  489. }
  490.  
  491. }

实践周java基础软件开发app之五子棋的更多相关文章

  1. Java基础-配置开发环境-安装JDK

    Java基础-配置开发环境-安装JDK 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.计算机基础知识 1>.计算机的组成 计算机有硬件与软件组成. 2>.硬件: 硬 ...

  2. 学java编程软件开发,非计算机专业是否能学

    近几年互联网的发展越来越好,在国外,java程序员已经成为高薪以及稳定职业的代表,虽然国内的有些程序员很苦逼,但是那只是少数,按照国外的大方向来看,程序员还是一个很吃香的职业.根据编程语言的流行程度, ...

  3. java基础-Eclipse开发工具介绍

    java基础-Eclipse开发工具介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 所谓工欲善其事必先利其器,即将身为一名Java开发工程师怎么能没有一款好使的IDE呢?今天就 ...

  4. java基础-Idea开发工具介绍

    java基础-Idea开发工具介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 之前给大家介绍过一款Java的IDE叫eclipse,有些功能用起来不是很得心应手,尤其是在导报的 ...

  5. Java基础之开发工具Eclipse的使用

    Eclipse简介 Eclipse是由IBM公司投资4000万美元开发的集成开发工具.它是目前最流行的Java集成开发工具之一,基于Java语言编写,并且是开放源代码的.可扩展的(Integrated ...

  6. 安装eclipse(tomcat配置maven搭建){Java基础之开发工具}

    安装eclipse 1.下载eclipse-jee-neon-3-win32-x86_64 zip 百度云盘 解压 2. 下载JDK 官网 JDK 8 JDK电脑上环境变量配置 Path路径    % ...

  7. java基础之开发环境搭建

    我们这里后续的所有课程都使用eclipse 来开发java代码,下面我们来搭建开发环境: 1.首先去java.sun.com去下载jdk,可以下载1.6 的版本2.安装JDK,最好安装在某个盘的跟目录 ...

  8. [学习笔记]java基础Java8SE开发环境搭建、第一个Java Hello World、Java程序的编译与执行

    本文作者:sushengmiyan 本文地址:http://blog.csdn.net/sushengmiyan/article/details/25745945 内容简介: ------------ ...

  9. java基础之开发环境配置

    一. 环境变量配置的原理 一.  配置环境变量path 如果我们按照上面的来编译和运行的话未免太过于麻烦了,那么在这里我们可以配置环境变量PATH 1.配置环境变量的步骤 这时可以直接来看效果 如果d ...

随机推荐

  1. SpringBoot&Dubbo&Zookeeper远程调用项目搭建

    序言 Dubbo一款分布式服务框架,作为阿里巴巴SOA服务化治理方案的核心框架,通过高性能和透明化的RPC实现服务的远程调用,对服务的负载均衡以及项目的耦合性提供很强的解决方式;具体Dubbo的介绍和 ...

  2. 一、基础篇--1.2Java集合-List、Set、Map区别

     List.Set.Map区别 三者关系如下: 结构特点 1.List和Set是存储单列数据集合,Map是存储键值对这样的双列数据集合: 2.List中存储的数据都是有序的,并且允许重复:Map中存储 ...

  3. PHP基本语句

    语句分支语句if语句if if.........elseif.......else if.....else if 的嵌套switch语句 循环语句 for 循环 函数 函数的4要素::返回类型,函数名 ...

  4. 对《疯狂Spring Cloud微服务架构实战》作者的疑问

    Cloud的程序都是用的内部Tomcat,即使把一个大App分成独立小块,能应付得了你们当年人力运维的大量请求涌入吗? 真不知道淘宝怎么做到的双11一直不垮?真实互联网生产环境是充斥图书市场中的所谓S ...

  5. git使用遇到的问题

    1.我新建了一个django项目,然后又在git上新建了一个仓库,然后我在django的项目文件内,将git上的项目clone到这个文件内的时候 git clone https://gitee.com ...

  6. 微信小程序---交互反馈

    1.学习大纲: 2.showToast(): wx.showToast({ title: '成功', icon: 'success', duration: }) 3.hieToast(): wx.sh ...

  7. 连接Xshell

    连xshell之前先进入[root@localhost zxj]# vim /etc/ssh/sshd_config, 将115行删除注释改为UseDNS  no, 保存重启sshd(xshell)的 ...

  8. Hibernate 持久化对象和一级缓存

    关于如何手动创建Hibernate,Hibernate初了解已经介绍了,接下来了解持久化对象和一级缓存. Hibernate的持久化类有三种状态: 1.Transient瞬时态:持久化对象没有唯一标识 ...

  9. beego 注解路由

    场景描述:使用注解路由,不起作用. 额外描述: 路由的添加都写在 main函数中了,同时未设置 beego.BConfig.RunMode ="dev"也未引入 :routers包 ...

  10. 引用dll出现了黄色感叹号

    今天引用一个dll的时候出现了一个小感叹号,重新生成也无济于事,如下图 原因是,被引用的项目使用的是.NET2.0版本,而当前项目使用的是.NET3.5版本,所以出现了错误 解决办法把当前项目和引用项 ...