前言
三子棋又叫九宫棋、圈圈叉叉、一条龙、井字棋等。
三子棋游戏规则:三子连成一片即为赢,如果双方都没有连成线,即为平局。
一、如何实现?
1.棋盘大小如何确定?
我们要实现一个3×3的棋盘,就需要定义一个3行3列的数组,但是数组的下标从0开始,玩家选择落子坐标很不方便,所以要定义一个4×4的数组,第0行第0列不使用,如下图红框内的行和列不使用。这样就方便玩家选择落子坐标。
2.如何判定输赢?
三子棋的规则很简单,只要判断每一行、每一列、对角线中是否有连成线的,即为赢。
代码思路:
1、判断是否有相同的行并且不能为空格(数组初始化为空格)。
2、判断是否有相同的列并且不能为空格。
3、判断主次对角线是否相同并且不能为空格。
4、棋盘下满后是否为平局。
代码如下:
//判断谁赢,'X'表示玩家赢,'0'表示电脑赢,'p'表示平局 char IsWin(char map[ROWS][COLS], int row, int col) { int i = 0; int j = 0; int ret = IsFull(map, ROWS, COLS); //判断行 for (i = 1; i < row; i++) { if (map[i][1] == map[i][2] && map[i][2] == map[i][3] && map[i][1] != ' ') { return map[i][1]; } } //判断列 for (j = 1; j < col; j++) { if (map[1][j] == map[2][j] && map[2][j] == map[3][j] && map[1][j] != ' ') { return map[1][j]; } } //判断主对角线 if (map[1][1] == map[2][2] && map[2][2] == map[3][3] && map[1][1] != ' ') { return map[1][1]; } //判断次对角线 if (map[1][3] == map[2][2] && map[2][2] == map[3][1] && map[1][3] != ' ') { return map[1][3]; } //判断是否为平局 if (ret == 0) { return 'p'; } else { return ' ';//防止编译器报错 } }
注意:
1、三个值比较时不可以使用连等,==是关系操作符,==是从左到右进行运算的,计算表达式 a == b == c 时,首先会进行逻辑运算 a == b得出逻辑值1或0,得到的结果作为返回值,然后进行逻辑运算 “返回值” == c 得出逻辑值1或0,作为整个表达式的返回值。所以不能这样用。
2、判断完是否平局后,要加一个else,返回一个字符,不然编译器会报错:
因为编译器认为还有一种情况:当所有的if都不满足时,没有返回值,所以要加一个else返回一个对结果没有影响的字符。
二、具体代码实现
1.头文件game.h
#include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> #define ROW 3 #define COL 3 #define ROWS ROW+1 #define COLS COL+1 //初始化棋盘 void InitMap(char map[][COLS], int row, int col); //打印棋盘 void DisplayMap(char map[][COLS], int row, int col); //玩家落子 void PlayerMove(char map[][COLS], int row, int col); //电脑落子 void ComputerMove(char map[][COLS], int row, int col); //判断棋盘是否满,0表示满,1表示未满 int IsFull(char map[][COLS], int row, int col); //判断谁赢,'X'表示玩家赢,'0'表示电脑赢,'p'表示平局 char IsWin(char map[][COLS], int row, int col);
2.主函数main.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void menu() { printf("***********************************************\n"); printf("******** 三子棋 *********\n"); printf("***********************************************\n"); printf("*************** 1.play **************\n"); printf("*************** 0.exit **************\n"); printf("***********************************************\n"); } void game() { char map[ROWS][COLS]; char ret = ' ';//用来接收IsWin()的返回值 InitMap(map, ROWS, COLS);//初始化棋盘 DisplayMap(map, ROWS, COLS);//打印棋盘 do { PlayerMove(map, ROWS, COLS);//玩家落子 ret = IsWin(map, ROWS, COLS); if (ret == 'X') { printf("玩家赢......\n"); break; } else if (ret == 'p') { printf("平局......\n"); break; } ComputerMove(map, ROWS, COLS);//电脑落子 ret = IsWin(map, ROWS, COLS); if (ret == '0') { printf("电脑赢......\n"); break; } }while (IsFull(map,ROWS,COLS));//棋盘已满,结束循环 } void test() { int input = 0; srand((unsigned)time(NULL)); do { menu(); printf("请输入操作代码->"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏成功......\n"); break; default: printf("选择错误,请重新输入->\n"); break; } } while (input); } int main() { test(); return 0; }
3.函数game.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void InitMap(char map[][COLS], int row, int col) { int i = 0; int j = 0; for (i = 1; i < row; i++) { for (j = 1; j < col; j++) { map[i][j] = ' '; } } } void DisplayMap(char map[][COLS], int row, int col) { int i = 0; int j = 0; for (i = 1; i < row; i++) { for (j = 1; j <= col; j++) { printf("%3c",map[i][j]); if (j < col - 1) { printf(" | "); } } printf("\n"); if (i < row - 1) { for (j = 1; j < col; j++) { printf(" --- "); } } printf("\n"); } } void PlayerMove(char map[][COLS], int row, int col) { int x = 0; int y = 0; printf("玩家走->\n"); while (1) { printf("请选择落子坐标->"); scanf("%d %d", &x, &y); if (x >= 1 && x <= 3 && y >= 1 && y <= 3) { if (map[x][y] == ' ') { map[x][y] = 'X'; break;//落子成功就跳出循环 } else { printf("该位置已被占用请重新输入->\n"); } } else { printf("坐标非法,请重新输入......\n"); } } DisplayMap(map, ROWS, COLS); } void ComputerMove(char map[][COLS], int row, int col) { int x = 0; int y = 0; printf("电脑走->\n"); while (1) { x = rand() % 3 + 1;//1-3 y = rand() % 3 + 1;//1-3 if (map[x][y] == ' ') { map[x][y] = '0'; break; } } DisplayMap(map, ROWS, COLS); } //判断棋盘是否满,0表示满,1表示未满 int IsFull(char map[][COLS], int row, int col) { int i = 0; int j = 0; int count = 0;//计算落子过的格子 for (i = 1; i < row; i++) { for (j = 1; j < col; j++) { if (map[i][j] == 'X' || map[i][j] == '0') { count++; } } } if (count == ROW * COL) { return 0;//满 } else { return 1; } } //判断谁赢,'X'表示玩家赢,'0'表示电脑赢,'p'表示平局 char IsWin(char map[ROWS][COLS], int row, int col) { int i = 0; int j = 0; int ret = IsFull(map, ROWS, COLS); //判断行 for (i = 1; i < row; i++) { if (map[i][1] == map[i][2] && map[i][2] == map[i][3] && map[i][1] != ' ') { return map[i][1]; } } //判断列 for (j = 1; j < col; j++) { if (map[1][j] == map[2][j] && map[2][j] == map[3][j] && map[1][j] != ' ') { return map[1][j]; } } //判断主对角线 if (map[1][1] == map[2][2] && map[2][2] == map[3][3] && map[1][1] != ' ') { return map[1][1]; } //判断次对角线 if (map[1][3] == map[2][2] && map[2][2] == map[3][1] && map[1][3] != ' ') { return map[1][3]; } //判断是否为平局 if (ret == 0) { return 'p'; } else { return ' ';//防止编译器报错 } }
4、运行结果示例
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。
- 本文固定链接: https://zxbcw.cn/post/202334/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)