1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【至急】DXライブラリでオセロを作って記事にする

Last updated at Posted at 2024-12-06

この記事はSLP-KBIT AdventCalendar20246日目の記事です。

目次

・はじめに
・環境構築と基礎
・作ったもの一覧
・メイン関数最終形態
・おわりに

はじめに

こんにちは、Advent Calendar 6日目担当のkaedeです。現在時刻は12月6日17時です。完全に忘れていました。何も考えてなかったので最近触っているDXライブラリで簡単にゲームを作ります。
はい、よーいスタート。

環境構築や基礎

正直、環境構築はよくわかってません。ですが皆さんあちらの方へ行かれるようです。
ゲームの設計についてはこのサイトが参考になります。公式リファレンスを見ながら作りましょう。とりあえずメイン関数の骨組みは次の通り。

main.cpp
#include "DxLib.h"
#include"osero.h"
#include"keyboard.h"
#include<ctime>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    if (ChangeWindowMode(TRUE))return -1;
    SetGraphMode(640, 640, 16);
    if (DxLib_Init())return -1;
    if (SetDrawScreen(DX_SCREEN_BACK))return -1;
    srand((unsigned)time(NULL));

    Osero osero;
    osero.init();
    while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
        osero.draw_board();
        osero.move();
        if ( hitkey(KEY_INPUT_RETURN)) {
            osero.put_stone();
        }
    }

    DxLib_End();
    return 0;
}

osero.hkeyboard.hは自分で作る予定のものです。メイン関数の動作は

  1. DXライブラリやオセロクラスの初期化
  2. ゲームボードの表示
  3. プレーヤーの操作を受け付ける
  4. 3を受けて必要な処理を実行する
  5. 4の結果を表示(=2に戻る)

このような流れになる予定です。
それでは実装してきます。

作ったもの一覧

実装してきました。現在時刻は21時ぐらいです。4時間ほどでだいたい作れたのでまとめて紹介します。

keyboard.h

DXライブラリにはキーボード入力回数を扱う関数はないため自作する必要があります。ということで作ったものがこちら。KeyCodeはDXライブラリで定義されているマクロです。

hitkey.cpp
#include"DxLib.h"
#include"keyboard.h"

bool hitkey(int KeyCode) {
	bool f = false;
	while (CheckHitKey(KeyCode))f = true;
	return f;
}

osero.h

多いので関数の実装はほとんど省略します。汚コードを見る覚悟の準備ができた方はこちらも参考にしてください。

osero.h
#ifndef OSERO_H
#define OSERO_H

typedef struct {//座標
	int y;
	int x;
}P;

class Osero {
public:
	int board[8][8];//i行j列の石の色(-1, 0, 1)
	int color[3];//(0, 1, 2) = (黒, 緑, 白)
	int dx[8] = { 0,1,1,1,0,-1,-1,-1 };//xの8方向
	int dy[8] = { -1,-1,0,1,1,1,0,-1 };//yの8方向
	int turn = 1;//現在の手番色
	int pturn, cturn;//プレーヤー、コンピューターの手番色
	P p;//カーソル
	void init();
	void draw_board();
	void move();
	void put_stone();
	bool check_stone(int y, int x);
	void res();
};

#endif

きたないですね。各関数の簡単な説明を書いておきます。

init.cpp
void init();//board, color, p, turnの初期化
draw_board.cpp
void draw_board() {
	for (int i = 0; i < 8; i++) {
		for (int j = 0; j < 8; j++) {
			//緑の正方形を間をあけて描写
			DrawBox(j * 80 + 1, i * 80 + 1, j * 80 + 80, i * 80 + 80, color[1], TRUE);
			//黒, 緑, 白の石を描写
			DrawCircle(j * 80 + 40, i * 80 + 40, 30, color[board[i][j]+1], TRUE);
		}
	}
	//プレイヤーのカーソル(手番色の小さい正方形)を描写
	DrawBox(p.x * 80 + 3, p.y * 80 + 3, p.x * 80 + 15, p.y * 80 + 15, color[pturn+1], TRUE);
}

この関数ではゲームボード、石、プレイヤーのカーソルを描写します(下画像参照)。
現在の手番と色の番号を1(白)、-1(黒)で表現しているため、colorにアクセスするときはboard+1しています。
手抜きポイントとして、マスの境界線は描写していません。画像の境界線は黒い線や長方形ではなく、何も描写されてないだけです。
スクリーンショット 2024-12-11 200243.png

move.cpp
void move();//上下キーで移動、ゲームボード外へ行かないように調整
put_stone.cpp
void put_stone();//check_stone()で置けるか確認し、boardとturnを更新
check_stone.cpp
bool check_stone(int y,int x);//y行x列マスに石を置けるならtrue
res.cpp
void res();//結果発表~~

メイン関数最終形態

上で用意したものを使って最終的にこんなものができました。

main.cpp
#include "DxLib.h"
#include"osero.h"
#include"keyboard.h"
#include<ctime>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    if (ChangeWindowMode(TRUE))return -1;
    SetGraphMode(640, 640, 16);
    if (DxLib_Init())return -1;
    if (SetDrawScreen(DX_SCREEN_BACK))return -1;
    srand((unsigned)time(NULL));

    Osero osero;
    osero.init();
    while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
        osero.draw_board();
        osero.move();
        if ( hitkey(KEY_INPUT_RETURN)) {
            osero.put_stone();
        }
        bool f = true;
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if (osero.check_stone(i, j))f = false;
            }
        }
        if (f)break;
    }

    while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
        osero.res();
        if (hitkey(KEY_INPUT_RETURN))break;
    }

    DxLib_End();
    return 0;
}

ゲームは次のように進行します。

  1. DXライブラリとOseroクラスの初期化
  2. ゲームボード、石、カーソルの表示
  3. 十字キーでカーソルを動かす
  4. Enterが押されると次のどちらかを実行
    1. プレーヤーの手番の場合、カーソルがあるマスに石を置こうとする
    2. コンピューターの手番の場合、石を置けるマスからランダムに選択して置こうとする
  5. 石を置けなくなっているか調べる
    1. 置ける場合2に戻る
    2. 置けない場合はbreakする
  6. 石を数えて勝敗を表示する

おわりに

現在時刻は22時ぐらいです。ここでタイマーストップ。記録はだいたい5時間でした。完装した感想ですが、とりあえず終わってよかったです。完装したとは言いましたがいろいろ足りてないと思います。後、とにかく汚い。例えば、ここには載せてないですが、put_stone()check_stone()はほぼ同じコードを書いているのでもうちょっとやりようがあったと思います。
もういい時間なのでこの記事はおしまいです。ここまで読んでくださりありがとうございました。


変更とか
ゲームボード描写の説明を追記しました。また、githubにコードを追加しました。
記事内で"オセロ"を"othello"ではなく"osero"と表記していますが仕様です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?