目录
1.游戏介绍
三子棋又名井字棋,相信大家小时候都玩过,在一个3x3的棋盘上下棋,最先实现三字连成一条线的玩家获得胜利。
2.程序构成
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>// rand srand
#include <time.h>// time
#include <windows.h>//Sleep
#define ROW 3
#define COL 3
//初始化棋盘
void init_board(char board[ROW][COL], int row, int col);
//打印棋盘
void print_board(char board[ROW][COL], int row, int col);
//玩家下棋
void player_input(char board[ROW][COL],int row,int col);
//电脑下棋
void computer_input(char board[ROW][COL], int row, int col);
//判断结果(输 赢 平局)
//玩家赢返回 '* ',电脑赢返回 '# ',返回 'B'(游戏继续),返回 'C'(平局)
char is_win(char board[ROW][COL], int row, int col);
//判断棋盘是否已满,没满返回0(继续游戏),满了返回1(平局)
int is_full(char board[ROW][COL], int row, int col);
game.c
#include "game.h"
void init_board(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void print_board(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
// %c | %c | %c ;
for (j = 0; j < col; j++)
{
printf(" %c ",board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
//---|---|---
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < row - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
void player_input(char board[ROW][COL], int row, int col)
{
printf("玩家请下棋->\n");
int x = 0;
int y = 0;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col && board[x - 1][y - 1] == ' ')
//x = 1 2 3; y = 1 2 3; 不懂数组的人玩这个游戏,并不知道数组的坐标,例如第一行第一列的坐标是0,0,方便游客游玩我们将每个坐标 + 1
{
board[x-1][y-1] = '*';//当我们输入1 ,1 将第一行第一列下棋为 * 时,数组这里 - 1,对应数组坐标 0,0
break;
}
else if(board[x - 1][y - 1] != ' ')//坐标不为空格时表示已经有棋
{
printf("此格已经有棋子,请重输入->\n");
}
else//最后一种可能就是坐标输入超出棋盘坐标
printf("超出棋盘,重新输入->\n");
}
}
void computer_input(char board[ROW][COL], int row, int col,int ret)
{
printf("电脑下棋中->\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
Sleep(2000);
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
char is_win(char board[ROW][COL], int row, int col)
{
//横排判断
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
int count1 = 0;
for (j = 0; j < col-1; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')
count1++;
}
if (count1 == col - 1)
{
return board[i][j];
}
}
//数列判断
for (j = 0; j < col; j++)
{
int count2 = 0;
for (i = 0; i < row - 1; i++)
{
if (board[i][j] == board[i + 1][j] && board[i][j] != ' ')
count2++;
}
if (count2 == row - 1)
{
return board[i][j];
}
}
//右斜线判断,从左上角判断到右下角
int count3 = 0;
for (i = 0; i < row-1; i++)
{
if (board[i][i] == board[i + 1][i + 1] && board[i][i] != ' ')
{
count3++;
}
if (count3 == col - 1)
{
return board[i][i];
}
}
//左斜线判断,从右上角判断到左下角
int count4 = 0;
for (i = 0; i < row - 1; i++)
{
if (board[i][row - 1 - i] == board[i+1][row - 2 - i] && board[i][row - 1 - i] != ' ')
{
count4++;
}
if (count4 == row - 1)
{
return board[i][row - 1 - i];
}
int x =is_full(board, ROW, COL);
if (x == 0)
{
return 'B';
}
else
{
return 'C';
}
}
}
int is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
while(1)
{
int count = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
break;
}
else
{
count++;
}
}
if (count == row * col)//棋盘所有格子数等于 行 X 列
{
return 1;
}
}
}
}
test.c
#include "game.h"
void menu()
{
printf("**********1.play**********\n");
printf("**********0.exit**********\n");
}
void game()
{
char board[ROW][COL] = { 0 };
srand((unsigned int)time(NULL));
init_board(board, ROW, COL);
print_board(board, ROW, COL);
//先初始化棋盘再打印棋盘,不能将执行顺序搞反
while (1)
{
player_input(board, ROW, COL);
print_board(board, ROW, COL);
char ret = is_win(board,ROW,COL);//is_win返回一个值给ret来判断游戏结果,* 玩家赢 # 电脑赢 C 棋盘满 平局
if (ret == '*')
{
printf("恭喜你赢了!!!\n");
break;
}
else if(ret == '#')
{
printf("很遗憾电脑赢了,再接再厉\n");
break;
}
else if (ret == 'C')
{
printf("棋盘已满,平局\n");
break;
}
computer_input(board, ROW, COL);
print_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret == '*')
{
printf("恭喜你赢了!!!\n");
break;
}
else if (ret == '#')
{
printf("很遗憾电脑赢了,再接再厉\n");
break;
}
else if (ret == 'C')
{
printf("棋盘已满,平局\n");
break;
}
}
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择 -->");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
3.游戏思路和实现
1.创建棋盘并打印
先创建出一个棋盘数组,行为ROW,列为COL
创建形参row 和 col来接收ROW 和 COL 的值
char board[ROW][COL] = { 0 };
init_board(board, ROW, COL);
print_board(board, ROW, COL);
//初始化棋盘
void init_board(char board[ROW][COL], int row, int col);
init_board 程序构成:
void init_board(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘
void print_board(char board[ROW][COL], int row, int col);
print_board程序构成:
void print_board(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
// %c | %c | %c ;
for (j = 0; j < col; j++)
{
printf(" %c ",board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
//---|---|---
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < row - 1)
{
printf("|");
}
}
}
printf("\n");
}
}
竖排列可以理解为
需要三行 ' ' | ' ' | ' ' (红色圈的地方)当棋盘是3(ROW)x3(COL)时,需要row行
需要三个 ' ' 和二个 | (红绿色重叠部分)
当棋盘是3(ROW)x3(COL)时,需要col个 ' ' 和col-1个 |
横行可以理解为
需要俩行 ---|---|--- (红色圈的地方) 当棋盘是3(ROW)x3(COL)时,需要row-1行
每行需要三个 --- 和二个 | (红绿色重叠部分)
当棋盘是3(ROW)x3(COL)时,需要col个 --- 和col-1个 |
2.玩家和电脑实现下棋步骤
player_input(board, ROW, COL);
computer_input(board, ROW, COL);
srand((unsigned int)time(NULL));//
rand函数可以返回一个整型随机数值,但是起点是一样的,所以每次rand的随机值都是一样的
例如这次rand是 2 ,15 ,33 ,1,44,下次程序执行还是 2 ,15 ,33 ,1,44,
srand可以初始化rand的起点,这时候使用time函数给srand随机的值,rand就可以每次返回不同的整型数值了。
具体请看
玩家下棋:
void player_input(char board[ROW][COL], int row, int col)
player_input 程序构成 :
void player_input(char board[ROW][COL], int row, int col)
{
printf("玩家请下棋->\n");
int x = 0;
int y = 0;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col && board[x - 1][y - 1] == ' ')
//x = 1 2 3; y = 1 2 3; 不懂数组的人玩这个游戏,并不知道数组的坐标,例如第一行第一列的坐标是0,0,方便游客游玩我们将每个坐标 + 1
{
board[x-1][y-1] = '*';//当我们输入1 ,1 将第一行第一列下棋为 * 时,数组这里 - 1,对应数组坐标 0,0
break;
}
else if(board[x - 1][y - 1] != ' ')//坐标不为空格时表示已经有棋
{
printf("此格已经有棋子,请重输入->\n");
}
else//最后一种可能就是坐标输入超出棋盘坐标
printf("超出棋盘,重新输入->\n");
}
}
方便游玩我们将坐标+1
电脑下棋:
void computer_input(char board[ROW][COL], int row, int col,int ret)
computer_input 程序构成:
void computer_input(char board[ROW][COL], int row, int col,int ret)
{
printf("电脑下棋中->\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
Sleep(2000);
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
3.判断双方谁先获得胜利或者双方平局
胜利条件:横排、竖排、x 交叉斜线(俩条)三个相同棋子连成一条线
平局条件:棋盘下满,无棋盘位可下
while (1)
{
player_input(board, ROW, COL);
print_board(board, ROW, COL);
char ret = is_win(board,ROW,COL);
if (ret == '*')
{
printf("恭喜你赢了!!!\n");
break;
}
else if(ret == '#')
{
printf("很遗憾电脑赢了,再接再厉\n");
break;
}
else if (ret == 'C')
{
printf("棋盘已满,平局\n");
break;
}
computer_input(board, ROW, COL);
print_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret == '*')
{
printf("恭喜你赢了!!!\n");
break;
}
else if (ret == '#')
{
printf("很遗憾电脑赢了,再接再厉\n");
break;
}
else if (ret == 'C')
{
printf("棋盘已满,平局\n");
break;
}
}
}
char is_win(char board[ROW][COL], int row, int col)
{
//横排判断
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
int count1 = 0;
for (j = 0; j < col-1; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')
count1++;
}
if (count1 == col - 1)
{
return board[i][j];
}
}
//数列判断
for (j = 0; j < col; j++)
{
int count2 = 0;
for (i = 0; i < row - 1; i++)
{
if (board[i][j] == board[i + 1][j] && board[i][j] != ' ')
count2++;
}
if (count2 == row - 1)
{
return board[i][j];
}
}
//右斜线判断,从左上角判断到右下角
int count3 = 0;
for (i = 0; i < row-1; i++)
{
if (board[i][i] == board[i + 1][i + 1] && board[i][i] != ' ')
{
count3++;
}
if (count3 == col - 1)
{
return board[i][i];
}
}
//左斜线判断,从右上角判断到左下角
int count4 = 0;
for (i = 0; i < row - 1; i++)
{
if (board[i][row - 1 - i] == board[i+1][row - 2 - i] && board[i][row - 1 - i] != ' ')
{
count4++;
}
if (count4 == row - 1)
{
return board[i][row - 1 - i];
}
int x =is_full(board, ROW, COL);
if (x == 0)
{
return 'B';
}
else
{
return 'C';
}
}
}
棋盘满时判断:
is_full(board, ROW, COL);
int is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
while(1)
{
int count = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
break;
}
else
{
count++;
}
}
if (count == row * col)//棋盘所有格子数等于 行 X 列
{
return 1;
}
}
}
}