用c语言编写三子棋程序
一、问题描述及文章声明
1. 问题描述
通过运用c语言代码实现三子棋程序的编写
2. 文章声明
如果您想系统学会如何编写三子棋程序,请先认真理解思路讲解中的整体思路分析,而后按照每个步骤认真学习,相信您会有所收获。
如果您只是想复制代码,直接跳到代码实现步骤即可。
二、基本流程
1. 在电脑安装Visual Studio 2022等编译器
可于b站查找按照流程
2. 创建一个新项目
(1). 在新建的项目中创建三个文件(如图所示)
test.c
文件用于编写程序运行代码
game.c
文件用于定义函数
game.h
文件用于函数声明
三、思路讲解
1. 编写代码时的整体思路分析
当你产生对一件事的想法时,你需要先基本捋清思路,而后在实行的时候不断进行优化,编写三子棋代码也是如此。
首先我们需要明白三子棋代码的整体框架。
- 当用户进行游戏时,首先需要有个选择窗口让用户进行选择,因此我们首先需要进行菜单界面的编写。
- 而当用户进入游戏时,我们需要给用户展现出一个棋盘,因此第二步便是进行棋盘的初始化代码编写。
- 当用户看到棋盘之后,便会开始进行游戏,因此我们需要先编写一个玩家下棋的函数,并在函数中对用户行为进行提醒。
- 我们都知道三子棋是回合制游戏,因此当用户下完棋之后,便需要电脑进行下棋,因此需要编写一个电脑下棋函数。而为了使电脑下棋具有随机性,我们运用<stdlib.h>库中的srand函数和rand函数以及<time.h>中的tiime函数,来随机生成数字。
- 当每一方下完棋后,需要进行判断输赢,因此我们需要编写一个判断输赢函数。而三子棋存在输、赢、平局三种可能,而平局则是在填满棋盘时双方都没取得胜利,因此编写一个判断是否填满棋盘函数来进行判断。
2. 代码的具体分布编写
(1). 菜单函数的设置
下面展示一些
菜单设置代码片
。
菜单函数设置—— 在game.c
文件下
#include <stdio.h>
void menu()
{
printf("*************************\n");
printf("******* 1. play *******\n");
printf("******* 0. exit *******\n");
printf("*************************\n");
}
int main()
{
int input = 0;//变量初始化
do
{
menu();//设置菜单函数
printf("请选择:>");//提醒用户进行选择
scanf("%d",&input);//获取用户输入
switch(input)
{
case 1:
printf("三子棋\n");
break;
case 0:
printf("退出游戏\n");
default:
printf("选择错误,请重新选择");
}
}while(input);//当input为非0时进入循环
return 0;
}
(2). 设置游戏函数
下面展示一些
游戏设置代码片
。
游戏函数设置——在test.c
文件下进行函数调用
//思路分析
void game()
{
//1.创建board数组 创建棋盘
//三子棋则为3*3棋盘
char board[3][3] = { 0 };//因为需要用空格代表棋盘,因此用char二维数组
char board[ROW][COL] = { 0 };//为了设棋盘可以更方便改变,我们将方括号中改成符号常数
//上述两行代码选取其中一行即可,本文以第二行代码为例
//2.初始化棋盘的函数
InitBoard();
//3.打印棋盘函数
DisplayBoard();
//4.玩家下棋
PlayerMove();
DisplayBoard();//下完棋后需重新打印棋盘
//5.电脑下棋
ComputerMove();
DisplayBoard();//下完棋后需重新打印棋盘
//6.判断输赢
IsWin();
}
(3). 棋盘初始化
初始化棋盘函数设置——在
game.h
文件下先定义Initboard()
函数
#pragma once
#define ROW 3 //设置符号变量
#define COL 3 //设置符号变量
void InitBoard(char board[ROW][COL], int row, int col);//进行函数声明
初始化棋盘函数设置—— 在
game.c
文件下
#include "game.h" //需要导入game.h文件,才能进行函数定义
void InitBoard(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] = ' ';//将数组中的所有元素替换成空格表示
}
}
}
(4). 打印棋盘函数
打印棋盘函数设置—— 在
game.c
文件下
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);//打印三个空格
if (j < col - 1)
{
printf("|");//打印|以隔开左右棋盘
}
}
printf("\n");
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");//打印---以隔开上下棋盘
}
}
printf("\n");
}
}
运行效果展示:
(5). 玩家下棋
玩家下棋函数设置—— 在
game.h
文件下进行声明
//总代码
#pragma once
#define ROW 3
#define COL 3
#include <stdio.h>
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL],int row,int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
玩家下棋函数设置—— 在
game.c
文件下进行定义
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋:>\n");
//很显然下面的代码需要重复运行,因此我们用while循环
while(1)
{
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;//玩家合法下棋后需要结束循环进行电脑下棋
}
else
{
printf("坐标被占用,请选择其他位置\n");
} }
else
{
printf("坐标非法,请重新输入\n");
}
}
}
玩家下棋函数设置—— 在
test.c
文件下进行使用
//game函数中到目前为止的总代码
void game()
{
char board[ROW][COL] = { 0 };
//初始化棋盘
InitBoard(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
//玩家下棋
PlayerMove(board, ROW, COL);
//每次下完棋需要重新打印棋盘
DisplayBoard(board, ROW, COL);
}
(6). 电脑下棋
电脑下棋函数设置—— 在
game.h
文件下进行声明
#pragma once
#define ROW 3
#define COL 3
#include <stdio.h>
#include <stdlib.h> //调用rand、srand函数
#include <time.h> //调用time函数
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL],int row,int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
电脑下棋函数设置—— 在
game.c
文件下进行定义
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
//rand()随机生成一个数
x = rand() % row; //%row 当row为3时生成0~2的数
y = rand() % col; //%col 当col为3时生成0~2的数
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
电脑下棋函数设置—— 在
test.c
文件下进行使用
//game函数中到目前为止的总代码
void game()
{
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//因为需要重复玩家输入和电脑输入,因此将他们加入循环
while (1)
{
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
}
}
(7). 判断输赢
判断输赢函数设置—— 在
game.h
文件下进行声明
//玩家赢 - '*'
//电脑赢 - '#'
//平局 - 'Q'
//继续 - 'C'
//判断是否取得胜利
char IsWin(char board[ROW][COL],int row ,int col );
//判断棋盘是否填满
int IsFull(char board[ROW][COL], int row, int col);
判断输赢函数设置—— 在
game.c
文件下进行定义
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
//循环遍历数组,当数组元素全部不为空格时,返回1。否则返回0。
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char IsWin(char board[ROW][COL], int row, int col)
{
//行
int i = 0;
int j = 0;
int flag = 0;
for (i = 0; i < row; i++)
{
flag = 1;
for (j = 0; j < col - 1; j++)//0~2
{
if (board[i][j] != board[i][j+1]) //判断是否相等
{
flag = 0;
}
}
if (flag == 1 && board[i][j] != ' ') //当一行的字符全相等且不为空时
{
return board[i][j]; //返回赢的一方的字符
}
}
//列
for (j = 0; j < col; j++)
{
flag = 1;
for (i = 0; i < row - 1; i++)
{
if (board[i][j] != board[i + 1][j])//判断是否相等
{
flag = 0;
}
}
if (flag == 1 && board[i][j] != ' ')//当一列的字符全相等且不为空时
{
return board[i][j];//返回赢的一方的字符
}
}
//斜对角
//左对角线
for (i = 0; i < row - 1; i++)
{
flag = 1;
if (board[i][i] != board[i + 1][i + 1]) //左对角线三个坐标分别为(0,0)(1,1)(2,2)
{
flag = 0;
}
}
if (flag == 1 && board[i][i] != ' ')//当对角线的字符全相等且不为空时
{
return board[i][i];//返回赢的一方的字符
}
//右对角线
for (i = 0; i < col - 1; i++)
{
flag = 1;
if (board[i][col - 1 - i] != board[i + 1][col - 2 - i])//右对角线三个坐标分别为(0,2)(1,1)(2,0)
{
flag = 0;
}
}
if (flag == 1 && board[i][col - 1 - i] != ' ')//当对角线的字符全相等且不为空时
{
return board[i][col - 1 - i];//返回赢的一方的字符
}
//判断棋盘是否填满
if (IsFull(board, ROW, COL) == 1)
{
return 'Q';
}
return 'C';
}
判断输赢函数设置—— 在
test.c
文件下进行使用
//game函数中到目前为止的总代码
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1)
{
PlayerMove(board, ROW, COL);
//玩家下完棋后,判断双方输赢,并将IsWin返回值用ret储存
ret = IsWin(board, ROW, COL);
if (ret != 'C') //当返回值不为'C'时,说明有人胜出或双方平局
{
break;
}
DisplayBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
//电脑下完棋后,判断双方输赢,并将IsWin返回值用ret储存
ret = IsWin(board, ROW, COL);
if (ret != 'C') //当返回值不为'C'时,说明有人胜出或双方平局
{
break;
}
DisplayBoard(board, ROW, COL);
}
//当循环结束时,ret中只可能存在'*','#'两种结果
//判断本局游戏的最终结果
if (ret == '*')
{
printf("玩家赢\n");
}
else if(ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
DisplayBoard(board, ROW, COL);
}
(8). 结果演示
此演示中我们仅以玩家赢的结果作为展示
四、代码实现
test.c
总代码展示
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("*************************\n");
printf("******* 1. play *******\n");
printf("******* 0. exit *******\n");
printf("*************************\n");
}
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1)
{
PlayerMove(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DisplayBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DisplayBoard(board, ROW, COL);
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if(ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
DisplayBoard(board, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;//变量初始化
do
{
menu();//设置菜单函数
printf("请选择:>");//提醒用户进行选择
scanf("%d", &input);//获取用户输入
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
default:
printf("选择错误,请重新选择");
}
} while (input);//当input为非0时进入循环
return 0;
}
game.c
总代码展示
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(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 DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋:>\n");
while (1)
{
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标被占用,请选择其他位置\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int IsFull(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++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char IsWin(char board[ROW][COL], int row, int col)
{
//行
int i = 0;
int j = 0;
int flag = 0;
for (i = 0; i < row; i++)
{
flag = 1;
for (j = 0; j < col - 1; j++)
{
if (board[i][j] != board[i][j+1])
{
flag = 0;
}
}
if (flag == 1 && board[i][j] != ' ')
{
return board[i][j];
}
}
//列
for (j = 0; j < col; j++)
{
flag = 1;
for (i = 0; i < row - 1; i++)
{
if (board[i][j] != board[i + 1][j])
{
flag = 0;
}
}
if (flag == 1 && board[i][j] != ' ')
{
return board[i][j];
}
}
//斜对角
for (i = 0; i < row - 1; i++)
{
flag = 1;
if (board[i][i] != board[i + 1][i + 1])
{
flag = 0;
}
}
if (flag == 1 && board[i][i] != ' ')
{
return board[i][i];
}
for (i = 0; i < col - 1; i++)
{
flag = 1;
if (board[i][col - 1 - i] != board[i + 1][col - 2 - i])
{
flag = 0;
}
}
if (flag == 1 && board[i][col - 1 - i] != ' ')
{
return board[i][col - 1 - i];
}
if (IsFull(board, ROW, COL) == 1)
{
return 'Q';
}
return 'C';
}
game.h
总代码展示
#pragma once
#define ROW 3
#define COL 3
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL],int row,int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//判断输赢
//玩家赢 - '*'
//电脑赢 - '#'
//平局 - 'Q'
//继续 - 'C'
char IsWin(char board[ROW][COL],int row ,int col );
//判断棋盘是否填满
int IsFull(char board[ROW][COL], int row, int col);