前言
C语言实现三子棋是结合我们对数组,函数,循环与分支等内容的考察。通过本篇文章你将学会如何制作出三子棋,看完相信你肯定能够掌握三子棋(文末附三子棋全部代码)
一、游戏规则
1、人和电脑双方轮流在格子里落子下棋,率先连成三个一线的视为胜利
2、棋盘被摆满棋子仍未分出胜利,视为平局
3、当未分出胜负时、可以再来一局
二、所需文件
三子棋并不是一项容易的代码,需要我们进行分文件编写。
如何分文件编写呢,我们可以把程序代码划分成多个文件,不要所有的代码都放在main.c里面,采用分模块的编程思想,进行功能划分,把每个功能不一样的单独放在一个c文件里,然后写头文件把它封装成可调用的一个函数,在主函数调用这个封装好的函数,编译的时候一起编译
好处:
1.功能划分清晰
2.方便调试,找出bug
3.主程序简洁,利于观看
来让给我们看看具体操作如下:
头文件中创建game.h ----用来进行函数的声明
源文件中创建game.c—函数具体实现 / test.c—主题流程
三.创建菜单
在开始前,我们需要先创建一个菜单,虽然创建菜单后不利于调试各个模块,但是在三子棋,扫雷游戏这些少功能模块的可以先创建菜单。
编辑
用do while循环实现菜单使用,switch语句进行菜单选择,然后进行调试观察菜单能不能正常打印
编辑
四,游戏核心内容实现
1.创建棋盘并初始化
棋盘实质是一个二维数组
在game.h里面定义ROW和COL分别表示行和列
编辑

编辑
2.棋盘打印
再设计一个函数把棋盘打印出来,不是很会描述,大抵情况如下图所示,棋盘打印可以用row,col来弄便于以后修改成多子棋
编辑
3.玩家下棋
创建一个函数,因为玩家不一定知道数组下标是从零开始的,所以我们可以设置一下,让玩家输入的坐标变成对应二维数组的坐标
编辑
4、电脑下棋
使用rand函数随机生成一个数,再对row,col取模,得到0到row,col之间的数,为电脑下棋的坐标
在game.c文件中实现电脑下棋函数。电脑随机下棋需要随机坐标引头文件#include <stdlib.h>,随机数生成需要头文件#include <time.h>。将电脑所下棋控制在棋盘内然后判断是否下在空棋盘内否则重下,while实现玩家下错棋子重新下直到下正确退出循环
编辑
编辑
5.胜负判断
当棋盘满了的时候,电脑没有地方下棋,就会进入死循环,因此我们需要判断一下游戏的胜负。
三种情况:玩家赢,电脑赢,平局
编辑
编辑
判断输赢的函数
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
//判断行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1]&&board[i][1] == board[i][2]&& board[i][0]!=' ')
{
return board[i][0];
}
}
//判断列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i]&& board[1][i] == board[2][i]&& board[0][i]!=' ')
{
return board[1][i];
}
}
//对角线判断
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//平局,创建is-full函数判断棋盘是否满了
if (is_full(board, ROW, COL))
return 'C';
return 'D';
}
6.game()函数内部具体实现
void game()
{
char board[ROW][COL];
//初始化棋盘的函数
Init_board(board, ROW, COL);
//打印棋盘
Print_board(board, ROW, COL);
while (1) {
//玩家下棋
player_move(board, ROW, COL);
Print_board(board, ROW, COL);
//判断输赢:玩家赢为*,电脑赢为#,平局为C,游戏继续为D
ret = is_win(board, ROW, COL);
if (ret != 'D')
{
break;
}
//电脑下棋
computer_move(board, ROW, COL);
Print_board(board, ROW, COL);
}
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else if (ret =='C')
printf("平局\n");
}
7演示
编辑
编辑
8.源码
game.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#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_move(char board[ROW][COL], int row, int col);
void computer_move(char board[ROW][COL], int row, int col);
//判断输赢
char is_win(char board[ROW][COL], int row, int col);
//判断是否满了
int is_full(char board[ROW][COL], int row, int col);
test.c
#include"game.h"
char ret;
void menu()
{
printf("**********************************\n");
printf("**** 1、开始游戏 0、退出游戏 *****\n");
printf("**********************************\n");
}
void game()
{
char board[ROW][COL];
//初始化棋盘的函数
Init_board(board, ROW, COL);
//打印棋盘
Print_board(board, ROW, COL);
while (1) {
//玩家下棋
player_move(board, ROW, COL);
Print_board(board, ROW, COL);
//判断输赢:玩家赢为*,电脑赢为#,平局为C,游戏继续为D
ret = is_win(board, ROW, COL);
if (ret != 'D')
{
break;
}
//电脑下棋
computer_move(board, ROW, COL);
Print_board(board, ROW, COL);
}
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else if (ret =='C')
printf("平局\n");
}
void test()
{
srand((unsigned int)time(NULL));
int input = 0;
do {
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:printf("三子棋,启动:\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("没有该选项,请重新选择\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
game.c
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void Init_board(char board[ROW][COL], int row, int col)
{
int i, j;
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, j;
for (i = 0; i < row; i++)
{
/*printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
if(i<row-1)
printf("---|---|---\n");*/
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < row - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
void player_move(char board[ROW][COL], int row, int col)
{
int x, y;
printf("玩家下棋");
printf("请输入要下棋的坐标:");
while (1) {
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 computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:\n");
while (1)
{//随机生成坐标
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] ='#';
break;
}
}
}
//在is win函数中实现,也可以不在头文件中声明
int is_full(char board[ROW][COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] != ' ')
return 0;
}
}
return 1;
}
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
//判断行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1]&&board[i][1] == board[i][2]&& board[i][0]!=' ')
{
return board[i][0];
}
}
//判断列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i]&& board[1][i] == board[2][i]&& board[0][i]!=' ')
{
return board[1][i];
}
}
//对角线判断
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[0][2] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//平局,创建is-full函数判断棋盘是否满了
if (is_full(board, row, col) == 1)
{
return 'C';
}
return 'D';
}
总结
本次三子棋学习告一段落,你学会了吗。
将三子棋详解和完整代码,反复阅读,坚持每天练习,为未来编写更高级的代码打下夯实的基础,相信你一定可以做到。
有不足的地方也可以指出来,我会虚心接受和改进的