您现在的位置是:群英 > 开发技术 > 编程语言
用C++如何编写简易三子棋小游戏?
Admin发表于 2022-01-08 17:42:40953 次浏览

    用C++如何编写简易三子棋小游戏?三子棋小游戏相信很多朋友都有玩过吧,也就是我们画圈圈叉叉井字的小游戏,使用代码实现三子棋的方法有很多,这里给大家分享的是使用C++实现的思路和代码,感兴趣的朋友就继续往下看吧。

    题目思想:

    用 3×3 的二维数组表示棋盘
    每一个棋子的格子,也就是每个元素表示三种状态:分别是
    1.未落子 ‘ '
    2.玩家落子 ‘X'
    3.电脑落子 ‘O'
    玩家通过输入数字作为落子位置的坐标(输入的行数与输入的列数)

    直接上代码解析

    1.创建出棋盘

#define _CRT_SECURE_NO_WARNINGS
//利用宏定义行和列
#define MAX_ROW 3
#define MAX_COL 3
#include <stdio.h>
#include <stdlib.h>


//  将初始化行和列的 '0' 变为空格 ' '
void init(char board[MAX_ROW][MAX_COL]) {
 //行初始化,将数组 0-2输出为' '  
 for(int row = 0; row < MAX_ROW; row++) {
  //列初始化
  for (int col = 0; col < MAX_COL; col++) {
   board[row][col] = ' ';
  }
 }
}

//  打印棋盘,定义printBoard,以二维数组的方式进行循环打印
void printBoard(char board[MAX_ROW][MAX_COL]) {
 for (int row = 0; row < MAX_ROW; row++) {
  for (int col = 0; col < MAX_COL; col++) {
   // 打印字符,使用 %c
   printf("%c", board[row][col]);
  }
  //每次打印完一行,进行换行操作,变成3×3的数组形成的棋盘
  printf("\n");
 }
}
int main() {
 //  首先创建棋盘并初始化
 //  这里不要用board[3][3],防止后面 3 与 3 搞混,可以利用宏定义
 char board[MAX_ROW][MAX_COL] = { 0 };
 //  使用 init 函数 初始化二维数组{0}应当变成空格  ' '
 //  此处也可以将 init函数定义中的双重 for 循环直接输入
 //  但将二维数组初始化为 ' ',表示了一个固定功能的逻辑,比较适合用函数定义的方法完成
 init(board);
 //  使用while循环,进行轮流落子
 while (1) {
  //1.先打印棋盘内容
  printBoard(board);
  //2.玩家落子
  //3.电脑落子
  //4.判定胜负
 }

 system("pause");
 return 0;
}

    确实打印出来了,但是由于初始化将二维数组中的元素变为了空格 ‘ ',所以输出结果看不到。

    2.修改棋盘,使之打印出的是 3×3 的带有方格的棋盘

void printBoard(char board[MAX_ROW][MAX_COL]) {
 for (int row = 0; row < MAX_ROW; row++) {
  //在打印每一行之前加入横线
  printf("+--+--+--+\n");
  for (int col = 0; col < MAX_COL; col++) {
   // 打印字符,使用 %c
   // 每打印一列,在打印之前加入|
   printf("| %c", board[row][col]);
  }
  //打印之后加入|,形成 3 列。
  printf("|");
  //每次打印完一行,进行换行操作,变成3×3的数组形成的纵线棋盘
  printf("\n");
 }//打印完所有行之后在加入横线,形成横线棋盘
 printf("+--+--+--+\n");
}

    3.玩家落子

//  玩家落子
void playerMove(char board[MAX_ROW][MAX_COL]) {
 printf("轮到玩家落子!\n");
 //加入while循环,保证用户输入错误时返回重新输入
 while (1) {
  printf("请输入落子位置的坐标(row col):");
  //添加屏幕输入模块,输入行和列坐标
  int row = 0;
  int col = 0;
  scanf("%d %d", &row, &col);
  //输入完了之后,一定要验证输入的内容,防止输入例如(10,20)超过棋盘坐标
  if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) {
   printf("您输入的坐标有误,请重新输入!\n");
   continue;//重新输入,继续循环
  }
  // 当前位置不为 ' ' ,说明有子了,也需要重新输入
  if (board[row][col] != ' ') {
   printf("当前位置有子,无法落子\n");
   continue;
  } 
  //玩家落子为 X ,结束当前循环
  board[row][col] = 'X';
  break;
 }
}

    4.电脑落子

// 电脑落子
void computerMove(char board[MAX_ROW][MAX_COL]) {
 printf("轮到电脑落子!\n");
 while (1) {
  //电脑落子时,产生随机位置,用到随机数种子,使随机数范围在棋盘坐标以内
  int row = rand() % MAX_ROW;
  int col = rand() % MAX_COL;
  if (board[row][col] != ' '){
   // 如果行列不是空格,说明有子了,就随机生成随机数
   continue;
  }
  board[row][col] = 'O';
  break;
 }
}

    这里使用了清屏操作,让每次输入完后进行一次清屏,具体代码在总体代码里附上

    5.判定胜负

//判断和棋的函数
int isFull(char board[MAX_ROW][MAX_COL]) {
 //如果在棋盘中找不到 ' ' ,就说明棋盘满了,只要找到 ' ' 说明没满
 //约定满了返回1,没满返回0
 for (int row = 0; row < MAX_ROW; row++) {
  for (int col = 0; col < MAX_COL; col++) {
   if (board[row][col] == ' ') {
    //没满
    return 0;
   }
  }
 }return 1;
}

// 判定胜负,由于要返回胜负,使用char定义
// 如果是玩家赢返回 X ,电脑赢返回 O,平局返回 P,胜负未分返回 ' '
char checkwinner(char board[MAX_ROW][MAX_COL]) {
 //1.检测所有行
 for (int row = 0; row < MAX_ROW; row++) {
  if (board[row][0] != ' ' &&
   board[row][0] == board[row][1]
   && board[row][0] == board[row][2]) {
   return board[row][0];
  }
 }
 //2.检测所有列
 for (int col = 0; col < MAX_ROW; col++) {
 if (board[0][col] != ' ' &&
  board[0][col] == board[1][col]
  && board[0][col] == board[2][col]) {
  return board[0][col];
 }
}
 //3.检测所有对角线
 if (board[0][0] != ' ' &&
  board[0][0] == board[1][1]
  && board[0][0] == board[2][2]) {
  return board[0][0];
 }
 if (board[2][0] != ' ' &&
  board[2][0] == board[1][1]
  && board[0][0] == board[0][2]) {
  return board[2][0];
 }
 // 判定和棋
 if (isFull(board)) {
  return 'p';
 }return ' ';

}

    这个结果中很多人肯定看到了问题,玩家赢的同时还在显示电脑落子,怎么改?

    6.注意还有一个问题:

    如图,在主函数中先进行玩家落子,后进行电脑落子,在电脑落子之前玩家就赢了。修改程序如下:

int main() {
 //  首先创建棋盘并初始化
 //  这里不要用board[3][3],防止后面 3 与 3 搞混,可以利用宏定义
 char board[MAX_ROW][MAX_COL] = { 0 };
 //  使用 init 函数 初始化二维数组{0}应当变成空格  ' '
 //  此处也可以将 init函数定义中的双重 for 循环直接输入
 //  但将二维数组初始化为 ' ',表示了一个固定功能的逻辑,比较适合用函数定义的方法完成
 init(board);
 char winner = ' ';
 //  使用while循环,进行轮流落子
 while (1) {
  //1.先打印棋盘内容
  printBoard(board);
  //2.玩家落子
  playerMove(board);
  winner = checkwinner(board);
  if (winner != ' ') {
   //胜负已分,结束循环
   break;
  }
  //3.电脑落子
  computerMove(board);
  //4.判定胜负
  winner = checkwinner(board);
  if (winner != ' ') {
   //胜负已分,结束循环
   break; 
  }
 }
 if (winner = 'X') {
  printf("恭喜你,获胜了!\n");
 }
 else if (winner = 'O') {
  printf("很遗憾,你有点菜呀!\n");
 }
 else {
  printf("你和电脑五五开!\n");
 }
 system("pause");
 return 0;
}

    全部函数

#define _CRT_SECURE_NO_WARNINGS
//利用宏定义行和列
#define MAX_ROW 3
#define MAX_COL 3
#include <stdio.h>
#include <stdlib.h>
#include <time.h>


//  将初始化行和列的 '0' 变为空格 ' '
void init(char board[MAX_ROW][MAX_COL]) {
 //行初始化,将数组 0-2输出为' '  
 for(int row = 0; row < MAX_ROW; row++) {
  //列初始化
  for (int col = 0; col < MAX_COL; col++) {
   board[row][col] = ' ';
  }
 }
 //设置随机数种子,为电脑落子
 //只要程序启动时,设置一次即可
 srand((unsigned int)time(0));
}

//  打印棋盘,定义printBoard,以二维数组的方式进行循环打印
void printBoard(char board[MAX_ROW][MAX_COL]) {
 //每次打印之前先清屏
 system("cls");
 for (int row = 0; row < MAX_ROW; row++) {
  //在打印每一行之前加入横线
  printf("+--+--+--+\n");
  for (int col = 0; col < MAX_COL; col++) {
   // 打印字符,使用 %c
   // 每打印一列,在打印之前加入|
   printf("| %c", board[row][col]);
  }
  //打印之后加入|,形成 3 列。
  printf("|");
  //每次打印完一行,进行换行操作,变成3×3的数组形成的纵线棋盘
  printf("\n");
 }//打印完所有行之后在加入横线,形成横线棋盘
 printf("+--+--+--+\n");
}

//  玩家落子
void playerMove(char board[MAX_ROW][MAX_COL]) {
 printf("轮到玩家落子!\n");
 //加入while循环,保证用户输入错误时返回重新输入
 while (1) {
  printf("请输入落子位置的坐标(row col):");
  //添加屏幕输入模块,输入行和列坐标
  int row = 0;
  int col = 0;
  scanf("%d %d", &row, &col);
  //输入完了之后,一定要验证输入的内容,防止输入例如(10,20)超过棋盘坐标
  if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) {
   printf("您输入的坐标有误,请重新输入!\n");
   continue;//重新输入,继续循环
  }
  // 当前位置不为 ' ' ,说明有子了,也需要重新输入
  if (board[row][col] != ' ') {
   printf("当前位置有子,无法落子\n");
   continue;
  } 
  //玩家落子为 X ,结束当前循环
  board[row][col] = 'X';
  break;
 }
}

// 电脑落子
void computerMove(char board[MAX_ROW][MAX_COL]) {
 printf("轮到电脑落子!\n");
 while (1) {
  //电脑落子时,产生随机位置,用到随机数种子,使随机数范围在棋盘坐标以内
  int row = rand() % MAX_ROW;
  int col = rand() % MAX_COL;
  if (board[row][col] != ' '){
   // 如果行列不是空格,说明有子了,就随机生成随机数
   continue;
  }
  board[row][col] = 'O';
  break;
 }
}


//判断和棋的函数
int isFull(char board[MAX_ROW][MAX_COL]) {
 //如果在棋盘中找不到 ' ' ,就说明棋盘满了,只要找到 ' ' 说明没满
 //约定满了返回1,没满返回0
 for (int row = 0; row < MAX_ROW; row++) {
  for (int col = 0; col < MAX_COL; col++) {
   if (board[row][col] == ' ') {
    //没满
    return 0;
   }
  }
 }return 1;
}

// 判定胜负,由于要返回胜负,使用char定义
// 如果是玩家赢返回 X ,电脑赢返回 O,平局返回 P,胜负未分返回 ' '
char checkwinner(char board[MAX_ROW][MAX_COL]) {
 //1.检测所有行
 for (int row = 0; row < MAX_ROW; row++) {
  if (board[row][0] != ' ' 
   && board[row][0] == board[row][1]
   && board[row][0] == board[row][2]) {
   return board[row][0];
  }
 }
 //2.检测所有列
 for (int col = 0; col < MAX_ROW; col++) {
 if (board[0][col] != ' ' 
  && board[0][col] == board[1][col]
  && board[0][col] == board[2][col]) {
  return board[0][col];
 }
}
 //3.检测所有对角线
 if (board[0][0] != ' ' &&
  board[0][0] == board[1][1]
  && board[0][0] == board[2][2]) {
  return board[0][0];
 }
 if (board[2][0] != ' ' &&
  board[2][0] == board[1][1]
  && board[0][0] == board[0][2]) {
  return board[2][0];
 }
 // 判定和棋
 if (isFull(board)) {
  return 'p';
 }return ' ';

}

int main() {
 //  首先创建棋盘并初始化
 //  这里不要用board[3][3],防止后面 3 与 3 搞混,可以利用宏定义
 char board[MAX_ROW][MAX_COL] = { 0 };
 //  使用 init 函数 初始化二维数组{0}应当变成空格  ' '
 //  此处也可以将 init函数定义中的双重 for 循环直接输入
 //  但将二维数组初始化为 ' ',表示了一个固定功能的逻辑,比较适合用函数定义的方法完成
 init(board);
 char winner = ' ';
 //  使用while循环,进行轮流落子
 while (1) {
  //1.先打印棋盘内容
  printBoard(board);
  //2.玩家落子
  playerMove(board);
  winner = checkwinner(board);
  if (winner != ' ') {
   //胜负已分,结束循环
   break;
  }
  //3.电脑落子
  computerMove(board);
  //4.判定胜负
  winner = checkwinner(board);
  if (winner != ' ') {
   //胜负已分,结束循环
   break; 
  }
 }
 if (winner = 'X') {
  printf("恭喜你,获胜了!\n");
 }
 else if (winner = 'O') {
  printf("很遗憾,你有点菜呀!\n");
 }
 else {
  printf("你和电脑五五开!\n");
 }
 system("pause");
 return 0;
}

    结果如下

    我们的三子棋棋盘小游戏就算结束啦!

    以上永C++实现简易三子棋小游戏的代码,本文只是提供了一种实现思路,代码仅供参考,需要的朋友可以了解看看,希望对大家学习C++有帮助,想要了解更多可以继续浏览群英网络其他相关的文章。

文本转载自PHP中文网

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

标签: c 三子棋
相关信息推荐
2022-05-07 17:29:58 
摘要:循环语句有四种。分别是:1、for循环,语法“for(初始值;条件;增加值){循环体}”;2、dowhile循环,语法“do{循环体}while(条件)”;3、while循环,语法“while(条件){循环体}”;4、foreach循环。
2022-01-05 18:43:17 
摘要:PHP里数值类型转布尔类型有什么方法?在实际的PHP项目中,有时候我们需要将数值类型转布尔类型,那么需要怎样来实现呢?接下来给大家分享三种实现方法,文中的示例代码介绍得很详细,有需要的朋友可以参考,接下来就跟随小编一起了解看看吧。
2022-12-09 17:52:56 
摘要:检测步骤:1、利用array_filter()函数过滤数组,去除空值元素,语法“array_filter(原数组)”,会返回一个过滤数组;2、利用count()函数获取原数组和过滤数组的长度,语法“count(原数组)”和“count(过滤数组)”;3、判断原数组长度是否等于过滤数组长度,语法“原数组长度==过滤数组长度”,如果等于则数组中没有空值,如果不等于则数组中有空值。
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部