【C语言】三子棋

三子棋游戏:一方三子连珠则赢,需要有交互界面———菜单,棋盘展示,玩家下棋,电脑下棋,判断输赢——电脑赢,玩家赢,平局,游戏继续。

将功能的实现分别用函数来表示。因此我们将代码分为三个文件——main.c, game.c, game.h。

其中game.c用来存放函数的定义,game.h用于存放函数的定义还有所需头文件声明,宏定义等。

在两个源文件中我们都需要进行自定义头文件的声明:

#include "game.h"

game.h :

#pragma once

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

#define ROW 3
#define COL 3
//菜单
void menu();

void game();

//初始化棋盘
void InitBoard(char board[ROW][COL],int row, int col);

//打印棋盘
void DisplayBoard(char board[ROW][COL],int row, int col);

//玩家下棋
void PlayerInput(char board[ROW][COL],int row ,int col);

//电脑下棋
void ComputerBoard(char board[ROW][COL], int row, int col);

//判断输赢
char IsWin(char board[ROW][COL], int row, int col);

构思:

程序开始运行时,用户则需进行选择:玩或者退出,选择玩游戏,则会进入游戏,这将由swicth语句实现。接着便是玩家下棋,电脑下棋,这是一个循环的过程,系统应该在玩家和电脑下棋时都分别判断一次输赢。有一方赢或者平局,都退出循环,和否则继续游戏。判断输赢后,下棋应该停止,再次弹出菜单,让用户选择是继续玩还是退出游戏(同时也应该考虑到用户输入错误的情况)。因此,菜单和游戏的接口应该放在一个循环里。这将构成主函数的部分。

而棋盘本身,我们将其定义成一个二维的字符数组。方便输入和遍历输出(即:展示棋盘)。

main.c部分

#include "game.h"

//下三子棋,三子相连则为赢

int main()
{
    int c, count = 0;
    srand((unsigned int) time (NULL));
    while(1)
    {
        menu();
        printf("请选择:");
        scanf("%d",&c);
        switch(c)
        {
        case 1:
            game();
            break;

        case 0:
            printf("游戏结束\n");
            count = 1;
            break;

        default:
            printf("输入错误,请重新输入\n");

        }

        if(count)
            break;
    }

    return 0;
}

自定义函数部分

交互界面,即:菜单。是用户开始游戏和退出游戏的选择窗口。

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

每次上一轮游戏结束后,都应该弹出菜单给用户继续选择

因此如果用户选择1,则需弹出一个全新的棋盘,这就包含了对棋盘的初始化,还有对棋盘的展示。我们不妨将其分别设为一个单独的函数,方便放入循环调用。

void InitBoard(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 DisplayBoard(char board[ROW][COL],int row, int col)
{
    int i, j;
    for(i = 0; i < row; i++)
    {
        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("--- ");
            }
        }
        printf("\n");
    }

}

之所以分开设为两个函数,是因为每次玩家下棋和电脑下棋后都需要展示棋盘。

玩家下棋:

你需要考虑玩家下棋的符号,即:棋子。(电脑也是如此)

且需考虑所下坐标是否已经被占位

void PlayerInput(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 ComputerBoard(char board[ROW][COL], int row, int col)
{
    printf("电脑下棋:\n");
    int x;
    int y;

    while(1)
    {
        x = rand()%row;
        y = rand()%row;
        if(board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
    }

}

注意要使用rand()函数,为了避免伪随机数的出现,我们需要调用srand(

即:在main()中调用:

srand((unsigned int) time (NULL));

这需要包含头文件:

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

判断棋盘是否满的函数:

每次一方下棋的结果除了电脑赢,玩家赢,平局外,还有游戏尚未结束

其中判断是否游戏继续和是否平局,取决于棋盘满没满。因此我们将其写成一个函数方便调用:

且将其设为static,将外部连接属性改为内部连接属性,因为它只需在game.c中被调用即可,这也可以保护函数。

static int IsFull(char board[ROW][COL], int row, int col)
{
    int i, j, count = 0;
    for(i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            if(board[i][j] == ' ')
                count = 1;

        }
    }

    return count;//当棋盘未满时返回真值
}

* 玩家赢
# 电脑赢
C 游戏继续
Q 平局

判断输赢函数:

char IsWin(char board[ROW][COL], int row, int col)
{
    int i;
    for(i = 0; i < row; i++)
    {
        if(board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
           //此处一定要注意,三子连珠要字符相等,但是不能等于空格!!!
            return board[i][1];
    }
    for(i = 0; i < col; i++)
    {
        if(board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
            return board[1][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))
        return 'C';
    else
        return 'Q';

}

将函数设为char的返回类型,可以方便主函数直接用char类型变量接收函数返回值,判断谁赢。而且函数内容也将更简洁。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值