三子棋游戏实现


前言

本文会简单介绍如何写出一个三子棋的程序的代码,希望大家能够看完,对自己有所帮助!


一、编程准备

创建3个文件:

  1. test.c:测试游戏
  2. game.c:游戏函数的实现
  3. game.h:游戏函数的声明

二、游戏思路(game.c)

  1. 创建菜单函数选择1进入游戏或者0退出游戏。
  2. 首先初始化棋盘然后再打印棋盘。
  3. 玩家下棋,电脑自动下棋,并打印出棋盘(玩家输入行、列坐标方式进行落子,'*' = 玩家落子,'#' = 电脑落子)
  4. 判断玩家是否赢,判断是否继续游戏。3种局面:玩家赢、电脑赢、以及 平局。然后,再回到步骤1是否选择1进入游戏或者0退出游戏。

1.菜单函数 menu( )

菜单界面函数实际上是游戏的界面目录,相当于餐馆当中的菜单,直接打印可。

void menu()
{
	printf("*****************************\n");
	printf("********  1. play   *********\n");
	printf("********  0. exit   *********\n");
	printf("*****************************\n");
}

2.初始化函数 InitBoard( )

初始化棋盘实质是让数组数组存放的空格。

ps:使用#define来定义行数和列数以实现多子棋效果

void InitBoard(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++)

        {

            board[i][j] = ' ';

        }

    }

3.打印棋盘 DisplayBoard( )

打印棋盘,本质上是打印二维数组的内容。

void DisplayBoard(char board[ROW][COL], int row, int col)

{

    int i = 0;

    for (i = 0; i < row; i++)

    {

        //1. 打印数据 

        int j = 0;

        for (j = 0; j < col; j++)

        {

            printf(" %c ", board[i][j]);

            if (j < col - 1)

                printf("|");

        }

        printf("\n");

        //2. 打印分割线 

        if (i < row - 1)

        {

            //printf("---|---|---\n"); 

            int j = 0;

            for (j = 0; j < col; j++)

            {

                printf("---");

                if (j < col - 1)

                    printf("|");

            }

            printf("\n");

        }

    }

}

 

4.玩家下棋 PlayerMove( )

  1. 玩家输入坐标,在玩家输入下棋的时候,定义了个静态局部变量坐标x和y,在执行代码的时候就可以保证上一次的值不会被销毁。
  2. 由于站在玩家的角度上来说,行&列通常都是以1为第一个的,而数组下标访问是从0开始的。所以我们要从1行1列为第一个进行打印。在程序实现就把输入坐标的值 - 1
  3. 玩家落子需要在棋盘范围内,玩家要在棋盘上空的地方落子,如果输入的坐标不满足上述两条件要重新输入。
  4. '*' = 玩家落子。
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");

        }

    }

}

 5.电脑随机下棋 ComputerMove( )

  1. srand((unsigned)time(NULL));要在主函数当中进行使用一次即可!
  2. rand() 函数产生的随机数是伪随机数。
  3. '#' = 电脑落子。
void ComputerMove(char board[ROW][COL], int row, int col)

{

    int x = 0;//0~row-1 

    int y = 0;//0~col-1 



    printf("电脑下棋:>\n");

    while (1)

    {

        x = rand() % row;

        y = rand() % col;

        if (board[x][y] == ' ')

        {

            board[x][y] = '#';

            break;

        }

    }

}

 

6.判断输赢  IsWin( )

思路:判断行以及列和对角线相不相等,但是不能空格也相等。

每次落子对输赢进行判断,这里可以定义一个用于接收输赢的标志符ret

  1. 玩家赢,ret为*时;电脑赢,ret为#时;
  2. IsFull( )函数:遍历二维数组,如果数组中有空格则返回0表示棋盘未下满,返之返回1表示棋盘已下满。
  3. 平局,ret为Q时;
  4. 当ret为C时,继续轮流下棋的过程。
int IsFull(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++)

        {

            if (board[i][j] == ' ')

            {

                return 0;

            }

        }

    }

    return 1;

}

char IsWin(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[0][i];

        }

    }

    //对角线 

    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')

        return board[1][1];

    if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')

        return board[1][1];

    //平局 

    if (IsFull(board, row, col) == 1)

    {

        return 'Q';

    }

    //继续 

    return 'C';

}


 

最后将以上函数在game.h文件上声明并在test.c中引用该头文件,以下是头文件内容

ps:使用#pragma once 是为了防止文件重复引用造成二义性

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 3
#define COL 3

//初始化棋盘
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);

 

三、测试代码

#define _CRT_SECURE_NO_WARNINGS	
#include "game.h"

void menu()
{
	printf("*****************************\n");
	printf("********  1. play   *********\n");
	printf("********  0. exit   *********\n");
	printf("*****************************\n");
}

void game()
{
	char board[ROW][COL] = { 0 };
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	//下棋
	char ret = 0;
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下棋
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
			break;
	}
	if (ret == '*')
		printf("玩家赢\n");
	else if (ret == '#')
		printf("电脑赢\n");
	else
		printf("平局\n");
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);//1 0 4
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择!\n");
			break;
		}
	} while (input);

	return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值