Java实现简单井字棋小游戏代码实例

Java第一次实验,老师让做一个井字棋,电脑随机下棋。

然后就想能不能聪明一点,可以判断出走哪一步棋;然后只能做到不会输,还是不够聪明,只能呆板地堵住用户,smartRobot的第三个判断逻辑找不到最佳位置,赢得概率比较小;而且我没事干时,想玩玩这个小游戏找找成就感,但每次都会赢了机器人,所以删删改改了四五次,最后才成。

可以选择谁先开始,但startGame里的代码更加冗余了。看着就很乱,但没想到好的办法。

smartRobot里的代码全部重写了,比原来更聪明一点了:下在四个角的位置时,能优先选择最佳位置;然后没有最佳位置时,再随便找一空的(随便找空四角位置使用for代替了,比原来更简短)。

然后smartRobot的第一个和第三个判断逻辑,也更聪明一点了。原来判断机器人和判断用户的逻辑,是放在一个for循环里的,但无法找到最佳位置,现在分开了。

机器人先开始时,才能发挥出来新添加的机器人的“小聪明”;但机器人原来的能力发挥不回来,只有用户先开始时才能发挥出原来的能力。所以各有利弊,无论谁先开始都能适应。如果机器人先开始,并且用户第一步棋不是下在四角的位置,那么用户就必输了。其他的情况一般都是平局了。

想到一个因为可以选择谁先开始而导致 startGame 代码冗余的问题的解决方法,就是使用局部内部类。内部类能访问到方法的局部对象。

主逻辑 startGame:

1. 用一个3X3的二维数组,存储棋盘;

2. 用户输入1~9下棋;

3. 判断是否合法,不合法则重新输入;

4. 将1~9转换成二维的坐标 x = (pos-1)/3, y = (pos-1)%3,再令二维数组相应位置为 'O';

5. 判断用户是否胜利,是则退出;再判断是否平局,是则退出;

6. 机器人下棋(根据输入等级,调用不同函数);

7. 打印棋盘显示出用户和机器人下的棋子;

8. 判断机器人是否胜利,是则退出;再判断是否平局,是则退出;都不是返回第1步。

isSuccessful 判断成功的逻辑:

判断所有行、列、对角线是否有连成一条线的,用字符相加的和判断即可

willBeSuccessful判断是否将要成功:

这里判断的是是否有行、列有两个相同棋子和一个空白,用字符相加的和判断。

calculate 计算行列对角线:

使用枚举类,来判断是计算行,还是计算列,还是计算左右对角线;计算行列时,传入一个1~3的数字表示是哪一行那一列。

smartRobot 的第一个判断逻辑:

如果棋子下在箭头指向的那个位置,那么一步棋就可胜利。

机器人先判断自己是否有这样一个位置,有则下在哪个地方,胜利;

方法是尝试填入所有空白地方,每填一次,判断一次 isSuccessful;

如果没有,再判断对方是否有这样一个位置,有则堵住这个地方。

smartRobot 的第三个判断逻辑:

如果棋子下在箭头指向的位置,那么再下一步必会胜利,因为下在了那个地方,第三列、第三行都是两个棋子了,无论对方堵哪里,都会失败。

也是机器人先判断自己是否有这样一个位置,有则下;

调用 willBeSuccessful 判断是否有这样的位置。

没有则再判断对方是否有这样的位置,有则堵住。

smartRobot 的第零个和第二个判断逻辑:

处理四个角和中心的位置,如果用户下在了中心,那么机器人必须至少有两个棋子下在四角位置才能保证不输。

更改了无数次的代码:

import java.util.Arrays;
import java.util.Scanner;

public class Experiment_1 {
  public static void main(String[] args) {
    ThreeChess game = new ThreeChess();
    game.startGame();

  }
}

class ThreeChess{
  private char[][] chessBoard = new char[3][3];
  private int size = 0; //已经下的棋数
  private final int CAPACITY = 9; //总共可下的棋数

  ThreeChess(){
    for(char[] line : chessBoard){ //初始化棋盘
      Arrays.fill(line, ' ');
    }
  }

  //【游戏开始】
  public void startGame(){
    System.out.println("┌───┬───┬───┐");
    System.out.println("│ 1 │ 2 │ 3 │");
    System.out.println("├───┼───┼───┤");
    System.out.println("│ 4 │ 5 │ 6 │");
    System.out.println("├───┼───┼───┤");
    System.out.println("│ 7 │ 8 │ 9 │");
    System.out.println("└───┴───┴───┘");
    System.out.println("输入 1 ~ 9 表示要下棋的位置");
    System.out.println("O是你的棋子,*是电脑的棋子");
    Scanner in = new Scanner(System.in);

    System.out.print("选择谁先开始:\n\t1.用户\n\t2.机器人\nInput: ");
    int whoFirst = in.nextInt();
    System.out.print("选择机器人智商:\n\t1. 999+\n\t2. 250\nInput: ");
    int level = in.nextInt();

    class Play{ //代码重用
      //方法返回-1表示退出
      int robotPlay(){
        if(level == 1)
          smartRobot();
        else
          sillyRobot();

        printChessBroad();
        if(isSuccessful() == -1) {
          System.out.println("机器人胜 (/ □ \\)");
          return -1;
        }else if (size == CAPACITY){
          System.out.println("==游戏平局==");
          return -1;
        }
        return 0;
      }
      int userPlay(){
        int pos;
        while(true){
          System.out.print("下棋位置: ");
          pos = in.nextInt();
          if(pos < 1
              || pos > 9
              || chessBoard[(pos - 1) / 3][(pos - 1) % 3] != ' '){
            System.out.println("输入错误,重新输入!");
            continue;
          } else {
            chessBoard[(pos - 1)/3][(pos - 1) % 3] = 'O';
            size++;
            break;
          }
        }

        if(isSuccessful() == 1){
          printChessBroad();
          System.out.println("恭喜,你胜了 ╰(*°▽°*)╯");
          return -1;
        } else if(size == CAPACITY){
          printChessBroad();
          System.out.println("==游戏平局==");
          return -1;
        }
        return 0;
      }
    }

    Play play = new Play();
    if(whoFirst == 2){
      while(true){
        //1.机器人下棋
        if(play.robotPlay() == -1)
          return;

        //2.用户下棋
        if(play.userPlay() == -1)
          return;
      }
    } else {
      while(true){
        //1.用户下棋
        if(play.userPlay() == -1)
          return;

        //2.机器人下棋
        if(play.robotPlay() == -1)
          return;
      }
    }
  }

  //【机器人下棋】
  private void sillyRobot(){ //笨机器人
    int l, c;
    while(true){
      l = (int)(Math.random() * 3);
      c = (int)(Math.random() * 3);
      if(chessBoard[l][c] == ' '){
        chessBoard[l][c] = '*';
        break;
      }
    }
    size++;
  }

  private int corner = 2;
  private void smartRobot(){ //无法战胜的机器人
    if(chessBoard[1][1] == ' '){ //抢占中心位置
      chessBoard[1][1] = '*';
      size++;
      return;
    }

    //1.判断是否可以下一个棋子就胜利(不能放在一起同时判断,否则有可能错误最佳位置)
    for(int i = 0; i < 3; i++){
      for(int j = 0; j < 3; j++){
        if(chessBoard[i][j] == ' '){ //【1】如果这个位置没有棋子,就尝试下载这个地方,看看是否可以胜;
          chessBoard[i][j] = '*';
          if(isSuccessful() == -1){ //【1】如果胜的话,就下在这个地方了,返回即可;
            size++;
            return ;
          }
          else
            chessBoard[i][j] = ' ';
        }
      }
    }

    for(int i = 0; i < 3; i++){
      for(int j = 0; j < 3; j++){
        //【2】逻辑同【1】
        if(chessBoard[i][j] == ' '){
          chessBoard[i][j] = 'O'; //【2】否则尝试用户下在这个位置
          if(isSuccessful() == 1){ //【2】如果用户下在这个位置会胜利,就占领它。
            chessBoard[i][j] = '*';
            size++;
            return ;
          } else
            chessBoard[i][j] = ' ';
        }
      }
    }

    //2.如果用户下在了中间的话,就赶紧占两个四角的位置,才能保证不输。优先级要比第一个低。用户没下在中间也可抢占。
    if(corner > 0){
      corner--;
      for(int i = 0; i < 3; i++){ //优先找四边中没有用户棋子的地方下
        if(i == 1)
          continue;
        boolean NoBigO = true;
        for(int j = 0; j < 3; j++){
          if(chessBoard[i][j] == 'O')
            NoBigO = false;
        }
        for(int j = 0; j < 3 && NoBigO; j++){
          if(chessBoard[i][j] == ' '){
            chessBoard[i][j] = '*';
            size++;
            return;
          }
        }
      }

      for(int i = 0; i < 3; i++){
        for(int j = 0; j < 3; j++){
          if(j == 1 || i == 1)
            continue;
          if(chessBoard[i][j] == ' '){
            chessBoard[i][j] = '*';
            size++;
            return;
          }
        }
      }
    } //end if

    //3.判断是否可以下一个棋子,从而再下一步可以胜利(不能放在一起判断)
    for(int i = 0; i < 3; i++){
      for(int j = 0; j < 3; j++){
        if(chessBoard[i][j] == ' '){
          chessBoard[i][j] = '*';
          if(willBeSuccessful(-1)){
            size++;
            return;
          } else
            chessBoard[i][j] = ' ';
        }
      }
    }

    for(int i = 0; i < 3; i++){
      for(int j = 0; j < 3; j++){
        if(chessBoard[i][j] == ' '){
          chessBoard[i][j] = 'O';
          if (willBeSuccessful(1)) {
            chessBoard[i][j] = '*';
            size++;
            return;
          } else
            chessBoard[i][j] = ' ';
        }
      }
    }

    sillyRobot();
  }

  //【打印棋盘】
  private void printChessBroad(){
    System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); //模拟清屏
    System.out.println("┌───┬───┬───┐");
    System.out.println("│ " + chessBoard[0][0] + " │ " + chessBoard[0][1] + " │ " + chessBoard[0][2] + " │");
    System.out.println("├───┼───┼───┤");
    System.out.println("│ " + chessBoard[1][0] + " │ " + chessBoard[1][1] + " │ " + chessBoard[1][2] + " │");
    System.out.println("├───┼───┼───┤");
    System.out.println("│ " + chessBoard[2][0] + " │ " + chessBoard[2][1] + " │ " + chessBoard[2][2] + " │");
    System.out.println("└───┴───┴───┘");
  }

  //【判断成功逻辑】
  private enum Choice{
    LINE,      //行
    COLUMN,     //列
    RIGHT_DIAGONAL, //右对角线
    LEFT_DIAGONAL; //左对角线
  }
  private int calculate(Choice choice, int i){ //计算行、列、对角线是否连成一条线
    switch (choice){
      case LINE:
        return chessBoard[i][0] + chessBoard[i][1] + chessBoard[i][2];
      case COLUMN:
        return chessBoard[0][i] + chessBoard[1][i] + chessBoard[2][i];
      case RIGHT_DIAGONAL:
        return chessBoard[0][0] + chessBoard[1][1] + chessBoard[2][2];
      case LEFT_DIAGONAL:
        return chessBoard[0][2] + chessBoard[1][1] + chessBoard[2][0];
    }
    return 0;
  }
  private int isSuccessful(){
    /*
    返回-1系统胜;返回1用户胜;返回0表示继续下棋。
    系统胜:126 == '*' + '*' + '*'
    用户胜:237 == 'O' + 'O' + 'O'
    */
    for(int i = 0; i < 3; i++){
      if(calculate(Choice.LINE, i) == 237 || calculate(Choice.COLUMN, i) == 237)
        return 1;
      if(calculate(Choice.LINE, i) == 126 || calculate(Choice.COLUMN, i) == 126)
        return -1;
    }
    if(calculate(Choice.LEFT_DIAGONAL, 0) == 237 || calculate(Choice.RIGHT_DIAGONAL, 0) == 237)
      return 1;
    if(calculate(Choice.LEFT_DIAGONAL, 0) == 126 || calculate(Choice.RIGHT_DIAGONAL, 0) == 126)
      return -1;
    return 0; //继续下棋
  }

  private boolean willBeSuccessful(int who){ //who:-1表示判断机器人的,+1表示判断用户的。
    //如果行、列、对角线有2个相同棋子的个数,则将会胜,
    //190 == 2 * 'O' + ' '
    //116 == 2 * '*' + ' '

    int n = 0;
    int s = (who == 1) ? 190 : 116; //用户or机器人要计算的值

    for(int i = 0; i < 3; i++){
      if(calculate(Choice.LINE, i) == s)
        n++;
      if(calculate(Choice.COLUMN, i) == s)
        n++;
    }
    //因为中心一定会被占的,所以就不用判断对角线了
    return n > 1;
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java如何获取一个随机数 Java猜数字小游戏

    本文实例为大家分享了Java获取一个随机数(及猜数字小游戏)的具体代码,供大家参考,具体内容如下 Math类概述: 该类Math包含用于执行基本数值运算的方法,例如基本指数,对数,平方根和三角函数. Math所有类都是静态的.可以直接类名.调用. 获取随机数的办法: 代码如下 public class SuiJi { public static void main(String[] args) { double d = Math.random(); System.out.println(d);

  • Java入门案列之猜拳小游戏

    最近正在学习Java基础知识,终于完成了第一个小demo,记录下来,算是一个小总结与整理,也希望可以帮助到别人. 先看看我写了哪些类: Player:玩家类: ComputerPlayer:机器人玩家类,主要用来实现机器人随机出拳: Game:游戏类,主要实现游戏规则的逻辑,以及正式游戏的逻辑: TestGuessBox:代码测试类: Player类: //玩家类 public class Player { private String name; //玩家昵称 private int scor

  • java实现拼图小游戏

    一个简单的拼图小游戏,供大家参考,具体内容如下 1.首先设计视图面板. 2.添加所需要的图片按钮. 3.最主要的是设计监听事件,添加图片的监听按钮,设定移动空白图片周围的按钮. 4.判断是否成功 . package sxy; import java.awt.Choice; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.MouseAdapter; import java.awt.event.MouseEv

  • java实现对对碰小游戏

    本文实例为大家分享了java实现对对碰的具体代码,供大家参考,具体内容如下 - 游戏实现功能:分别点击两张相邻的图像按钮进行交换(重点相邻),交换后的两个图像按钮的相邻水平或者垂直方向上,与之相同的图像超过规定个数后(这里规定为3个)就将其全部消除(置为空白按钮),上面的图像按钮也分别随之向下移动,将空白补齐(这里我们可以理解为图像按钮和空白按钮进行交换). - 游戏设计思路: 1.创建图像按钮数组,设置其基本属性: 2.给每个图像按钮配置相应的ID,用来标记图像信息,对于ID相同的按钮,图像也

  • Java控制台实现猜拳游戏小游戏

    本文实例为大家分享了Java猜拳游戏的具体代码,供大家参考,具体内容如下 先来看一下效果图: 首先我们创建一个Person类,这个类有name和score两个属性,有play这个方法,源代码如下: package com.samoy; public class Person { public String name; public int score; public Person(String name, int score) { this.name = name; this.score = s

  • java实现猜拳小游戏

    一天下午无聊,突发奇想做的一个简单的小游戏. 下面是我做的过程中思路与步骤:` /* 需求:由后台输入剪刀石头布,然后电脑随机输出一项,比较判断输赢 追加需求:可继续游戏,并当输入错误时提供重新输入 思路: 1.创建一个可以输入的渠道 2.能让电脑随机输出一个结果 3.用一些语句来判断比较 4.用do-while语句来完成继续游戏 5.在判断是否继续游戏时,只能输入Y/N,输入其他则重新输入 步骤: 1.输入格式:import java.util.Scanner; 2.随机格式:Math.ran

  • java实现扫雷小游戏

    本文实例为大家分享了java实现扫雷小游戏的具体代码,供大家参考,具体内容如下 代码: package GUI; import java.util.Random; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.awt.BorderLayout; import java.awt.GridLayo

  • Java实现简单井字棋小游戏代码实例

    Java第一次实验,老师让做一个井字棋,电脑随机下棋. 然后就想能不能聪明一点,可以判断出走哪一步棋:然后只能做到不会输,还是不够聪明,只能呆板地堵住用户,smartRobot的第三个判断逻辑找不到最佳位置,赢得概率比较小:而且我没事干时,想玩玩这个小游戏找找成就感,但每次都会赢了机器人,所以删删改改了四五次,最后才成. 可以选择谁先开始,但startGame里的代码更加冗余了.看着就很乱,但没想到好的办法. smartRobot里的代码全部重写了,比原来更聪明一点了:下在四个角的位置时,能优先

  • python实现简单井字棋小游戏

    用python实现的一个井字棋游戏,供大家参考,具体内容如下 #Tic-Tac-Toe 井字棋游戏 #全局常量 X="X" O="O" EMPTY=" " #询问是否继续 def ask_yes_no(question): response=None; while response not in("y","n"): response=input(question).lower() return respon

  • python实现井字棋小游戏

    本文为大家分享了python实现井字棋小游戏,供大家参考,具体内容如下 周五晚上上了python的选修课,本来以为老师是从python的基础语法开始的,没想到是从turtle画图开始,正好补上了我以前一些不懂的地方,有人讲一下还是比啃书好一点. 之前从图书馆借了一本python游戏编程,看了前面几章后就没怎么看了,晚上突然想看看,然后跟着教程写个游戏的.最后就有了这个井字棋的诞生,其实代码并不是很长,主要是思路,需要考虑的周全一点.代码写完后就和电脑下了好久的井字棋,一局都没赢,真的是很无奈了,

  • Python+Tkinter实现经典井字棋小游戏

    目录 演示 介绍 官方文档 tkinter.messagebox 源码 演示 介绍 首先来介绍一下GUI库Tkinter 主要模块: tkinter Main Tkinter module. tkinter.colorchooser 让用户选择颜色的对话框. tkinter.commondialog 本文其他模块定义的对话框的基类. tkinter.filedialog 允许用户指定文件的通用对话框,用于打开或保存文件. tkinter.font 帮助操作字体的工具. tkinter.messa

  • python实现带界面的井字棋小游戏

    目录 1.首先安装tkinter 2.初始化窗口 3.定义按钮 4.检查获胜的条件 今天我们用python+tkinter安装带界面的井字棋,效果如图所示. Tkinter 是 Python 的标准 GUI 库.Python 使用 Tkinter 可以快速的创建 GUI 应用程序.由于 Tkinter 是内置到 python 的安装包中.只要安装好 Python 之后就能 import Tkinter 库.而且 IDLE 也是用 Tkinter 编写而成.对于简单的图形界面 Tkinter 还是

  • 利用C语言实现三子棋(井字棋)小游戏

    本文实例为大家分享了C语言实现三子棋(井字棋)小游戏的具体代码,供大家参考,具体内容如下 推荐阅读顺序(不建议跳过) 先看实现之后的界面 -- 然后看分析程序要实现的步骤 -- 之后在看翻到test.c部分 -- 在test.c中找到main()函数 -- 从main函数的第一步开始看 -- 遇到自定义函数请到game.h源文件中找到相应函数的详情 辅助阅读: game.h文件中放的是函数的声明(引用头文件) game.c文件中放的是函数的详情(怎么用代码实现相应步骤的) test.c文件中放的

  • python入门之井字棋小游戏

    引言: 刚学python好几天了,从java到python,基础学起来确实比较容易,语法掌握,基本概念上都比较容易入脑. 唯一比较郁闷的是老想着用java的语法去学python代码,这点还需要后面慢慢掌握吧,相信学多种语言的你们也有这种经历吧. start:开始上代码了,希望有更好的逻辑思维来写,自己也是用最笨拙的思路去写的,如果有可以优化的代码请各位大神指教 #!/user/bin/python # -*- coding: utf-8 -*- import os import sys #棋盘模

  • C语言实现井字棋小游戏

    C语言实现简单的"井字棋游戏",供大家参考,具体内容如下 总体构造: 1.游戏菜单的逻辑实现 2.游戏本体的代码实现 part 1:游戏菜单的整体逻辑 ①简单的通过一个输入0和1的switch函数实现判断是玩游戏还是退出游戏的逻辑 输入1则进入游戏,而且打完game()即游戏本体之后因为do-while函数输入1会继续循环询问是否玩游戏 输入0则break退出游戏,且退出do-while循环,程序结束. int main() { int input = 0; srand((unsign

  • python实现简单的井字棋小游戏

    Python做三子棋游戏,这个是我刚开始了解做Python小游戏的时候第一个项目,因为简单好入手,实现它的过程是我开始摸索Python的GUI界面的入门之路.这个设计也都是按照自己对于这个游戏的理解,一步一步去实现它. 窗口 万能的窗口,实现窗口都可以进行简单的修改进行使用: from tkinter import * root = Tk()         #窗口名称 root.title("憨憨制作的三子棋") f1=Frame(root) f1.pack() w1 = Canva

  • C语言实现简单井字棋游戏

    本文实例为大家分享了C语言实现简单井字棋游戏的具体代码,供大家参考,具体内容如下 游戏截图 源代码 person.h //玩家对战 void person() { int i,j; initMap(map); //打印棋局 displayMap(map); //未分出胜负且棋局未落满子前无限循环 while(1) { //获取玩家下子位置 getXY(&i,&j); //玩家落子 setPiece(map,i,j); //清屏 system("cls"); //打印棋局

随机推荐