2020年4月の完全定年退職から、再度プログラミングを再開し、Embarcadero C++とBatchGoodによるるBCCForm and BCCSkeltonプログラミング、WIndows 10付属cs.exeとMSCompAssによるC#プログラミングで目覚ましく活躍し、多くの自作ソフトウェアを作ることが出来たのは、ひとえにこのPCのおかげでした。
//石の配置初期設定
private void InitTable() //解説:Initialize()から名称変更
{ //データテーブルを空き(0)で初期化
for(int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
dataTable[y, x] = 0;
}
} //中央に黒白石の初期配置
dataTable[3, 3] = dataTable[4, 4] = 1;
dataTable[4, 3] = dataTable[3, 4] = 2;
}
//空の桝目(x, y)から指定方向に裏返せる石の数を返す。置けない場合は0を返す。(解説:オリジナルでは置けない場合、-1を返していましたが、このメソッドの条件判定がすべて"> 0"であったので、falseらしく0を返すようにしました。)
//引数:座標(x, y)、自石色(黒-1、白-2)、指定座標周囲の方向(0-7)
public int numberCount(int x, int y, int diskColor, int dir)
{
if(dataTable[y, x] != 0)
return 0; //既に石が置かれている場合
int oponentColor = 3 - diskColor; //敵石の色(黒 - 1、白 - 2)
int dx = vectorTable[dir, 1], dy = vectorTable[dir, 0]; //設定方向のx、y座標差分(vectorTable参照)
int nextX = x + dx, nextY = y + dy; //設定方向1個先のx、y座標
if(nextX < 0 || nextX > 7 || nextY < 0 || nextY > 7)
return 0; //指定方向1個先が盤外の場合(一次チェック-無いと範囲外エラーとなる)
int numStone = 0; //(nextX, nextY)から指定方向へ続く敵石の数
while(dataTable[nextY, nextX] == oponentColor)
{
numStone++; //裏返すことが出来る敵石の数を増やす
nextX += dx; //指定方向に沿って(nextX, nextY)の桝目の先を
nextY += dy; //x、y座標差分を繰り返してチェック
if(nextX < 0 || nextX > 7 || nextY < 0 || nextY > 7)
return 0; //盤外の場合
}
if(dataTable[nextY, nextX] == diskColor) //敵石の連続が終わる座標をチェック
return numStone; //自石であれば裏返せる
else
return 0; //それ以外(空-0)の場合
}
//桝目(x, y)に石を置くことができるかを判定
public bool canPlace(int x, int y, int diskColor)
{
for(int dir = 0; dir < 8; dir++)
{
if(numberCount(x, y, diskColor, dir) > 0)
return true;
}
return false;
}
//盤上に石を置く場所があるか判定
public bool canPlace(int diskColor)
{
for(int y = 0; y < 8; y++)
{
for (int x = 0; x < 8; x++)
{
if(canPlace(x, y, diskColor))
return true;
}
}
return false;
}
/////////////////////////////////////////////////////////////////
//オセロゲーム(Othello.cs)
//原典:http://www.souzousha.iinaa.net/Source/Othello.txt
//オセロ(またはReversi):https://en.wikipedia.org/wiki/Reversi
//【用語】(解説:余計なようですが、一応こういう用語で統一しました。)
//Board - 盤
//Disks - 石
//Square - 升目
/////////////////////////////////////////////////////////////////
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Reflection; //Assemblyを使う為
using System.IO; //StreamReader/Writerを使用するのに必要
using System.Text; //Encoding.GetEncodingを使用するのに必要
namespace Othello
{ //アプリケーションクラス(解説:プログラムのエントリーポイント用のクラスです。)
public class App
{
[STAThread] //解説:これをいつも忘れないように。(SingleThreadApartment)
public static void Main()
{
OthelloForm of = new OthelloForm();
Application.Run(of);
}
}
//Othelloクラス
public partial class OthelloForm : Form
{ //ウィンドウコントロール
Label label; //ラベルコントロール
RadioButton radioButton1, radioButton2; //ラジオボタンコントロール
Button startButton, passButton, exitButton, datButton; //ボタンコントロール //表示関係
public Image image2disp = new Bitmap(412, 412); //表示用ビットマップ(幅412、高さ412)
//解説:オリジナルはでかかったのですが、マージンを入れてもこれだけで十分なので。又名称も変更しました。
public Graphics gr_image; //表示用ビットマップのグラフィックス
//解説:これも名称変更しました。
Brush bD = new SolidBrush(Color.DarkGreen); //ブラシ暗い緑色
Brush bW = new SolidBrush(Color.White); // 白色
Brush bB = new SolidBrush(Color.Black); // 黒色
Brush bG = new SolidBrush(Color.Gray); // 灰色
Pen pB = new Pen(Color.Black, 1); //ペン 黒色
Pen pW = new Pen(Color.White, 1); // 白色
Pen pG = new Pen(Color.DarkGray, 1); // 暗い灰色
Pen p1 = new Pen(Color.White, 2); // 白色(太さ2)
Pen p2 = new Pen(Color.White, 4); // 白色(太さ4)
//解説:変更なしです。
// ① Form1のMuseClickイベントハンドラをForm1_MouseClickに設定してください。
// ② Form1のLoadイベントハンドラをForm1_Loadに設定してください。
// ③ timer1コントロールをFormに貼り付け、timer1_Tickイベントハンドラ
// を指定してください。
// ④ label1コントロールを貼り付けてください。
// ⑤ radioButton1(Text="先攻"), radioButton2(Text="後"), button1(Text="開始"),
// button2(Text="パス")をForm1の上方に配置し, ボタンにはClickイベントハンドラ
// を指定してください。
// 解説:Formとロードイベントにマウスクリックイベント、TimerとTickイベント、Label、RadioButton x 2(Enabledの初期状態は不明)、Button(数不明)が必要とされることが分かりました。これらは自分で実装する必要があります。 //
using System; using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing; using System.Linq; // C# 2005以前の場合,Linqsを外すこと。
using System.Text; //Encoding.GetEncodingを使用するのに必要(オリジナルのままでは必要なし。)
// 解説:Visual Studioによるコンパイルの為にいくつかのDLLを使用しますが、MSConpAssでは不要です。なお、以下は機能拡張のために追加しました。 using System.Windows.Forms;
using System.Reflection; //Assemblyを使う為
using System.IO; //StreamReader/Writerを使用するのに必要
namespace Othello
{
public partial class Form1 : Form // 解説:Formから派生させているので、ここでフォームが作れます。
{
public Image image = new Bitmap(1000, 1000);// 表示用ビットマップ
public static Graphics g; // 表示用グラフィックス // 解説:↑が描画用のフィールドです。
public Boolean canPlace(int ii, int jj, int TB) // セル(ii, jj)に石を置くこと
{ // ができるかを判定。
for (int i = 0; i < 8; i++)
if (numberCount(ii, jj, TB, i) > 0) return true;
// 解説:オセロ盤の(ii、jj)座標の周囲8方向を、先手(TB==1)または後手
// (TB==2)について、おける場所がないかチェックし、一つでもあれ
// ば真、なければ偽を返します。
return false;
}
public Boolean canPlace(int TB) // 石を置く場所があるかを判定。
{
for (int ii = 0; ii < 8; ii++) for (int jj = 0; jj < 8; jj++)
if (canPlace(ii, jj, TB)) return true;
// 解説:先手(TB==1)または後手(TB==2)について、オセロ盤上でおける
// i場所がないか、ii(y)、jj(x)のネストfor文にすべての枠をチェックし、
// 一つでもあれば真、なければ偽を返します。
return false;
}
public Boolean judgeEnd() // 終了判定。
{
for (int TB = 1; TB < 3; TB++) if (canPlace(TB)) return false; // 解説:先手(TB==1)、後手(TB==2)共における場所がないかチェックし、
// 一つでもあれば偽、なければ真を返します。
return true;
}
public void replacePlane(int ii, int jj, byte TB) // 石の裏返し。
{ // 解説:「面の置き換え」は違和感があります。FlipStoneではないでしょうか?
byte [, ]Temp=new byte[8, 8];// 石の状態を作業領域に移して
for(int i=0;i<8;i++)for(int j=0;j<8;j++)Temp[i, j]=dTab[i, j]; // 解説:「石の状態を作業領域に移」す、とはオセロ盤をTempにコピーすることです。
for (int i = 0; i < 8; i++) // 作業領域を判定して(解説:正確には「オセロ盤を判定して」です。)
{
int num = numberCount(ii, jj, TB, i),ip = ii, jp = jj;
int di = procTable[i, 0], dj = procTable[i, 1];
if (num > 0) // 石を裏返す(解説:「(作業用盤の)石を裏返す」です。)
for (int j = 0; j <= num; j++, ip += di, jp += dj) Temp[ip, jp] = TB;
} // 解説:本来のオセロ盤のデータから裏返す(データを書き換える)石(のある枠)