🐈

JSP、Servlet、ClassとMVC、Singletonパタンを応用した「じゃんけんぽんゲーム」例文

2023/09/12に公開

前書き

今回は新しく学んだことでなく、今まで学んでいた物事を合わせて、ページの移動やデータの伝送がうまく作動する小さいプロジェクトを作ってみた。

名前は「じゃんけんぽんゲーム」。名前通りに、ジャン/ケン/ポンどっちかをランダムに選ぶコンピューターとじゃんけんぽんをするゲームである。

先生がかけた結果物の条件は下記のメッセージのようである。

上の条件のなかで、戦績を保存するために「Singleton」パタンを使って、両ページ(入力/出力するページ / 入力されたデータを扱うページ)で扱われる一部のデータを管理する方式を使った。

条件に合わせて作ったページの出来事は下記のようになる。ただし、コードの構成上1番最初(じゃんけんぽんを1回もしてない時期)には、両方の選んだじゃんけんぽんに当たるイメージが出力されない。これはこのまとめの後修正する予定である。

このプロジェクトを終えるに、約2時間半ぐらいかかった。コードも汚くて、CSSも何1つ書けなかったが、最小限の機能の作動はうまくいけるので、これからそのコードをまとめてみる。

例文のコード(簡単な流れ付き)

コードを見る前に、プロジェクトのながれを簡単にまとめる。

それではコードを見てみよう。コードの順番はプログラムが実行される順番と同じにしておいた。

HomeController.java

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HomeController")
public class HomeController extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		if(!request.getParameterNames().hasMoreElements()) { // Servletを実行するとき、つまり1番最初に実行されたとき
		request.getRequestDispatcher("RSPMain.jsp").forward(request, response);
		//現在のrequestとresponseインスタンスを持って、「"RSPMain.jsp"」に移動する。
		} 
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		//「"RSPMain.jsp"」からじゃんけんぽんボタンを押すと、POST方式によりここを実行する。
		
		//じゃんけんぽんに使って、結果を受ける変数宣言
		int mySel = 0;
		int comSel = 0;
		
		String mySelStr = "";
		String comSelStr = "";
		String result = "";
		String myFileString = "";
		String comFileString = "";
		
		if(request.getParameter("SCISSORS") == "") {
		//「"RSPMain.jsp"」で「ジャン」ボタンを押すと、上のif文の条件に入る。
		//つまり、私がジャンを選んだとき
			mySel = 1; // ジャンを「1」という値で区分する。1はジャン、2はケン、3はポンにする。
			mySelStr = "ジャン";
			myFileString = RSP.fileStringCheck(mySel);//上の「mySel」の値によって、適用するイメージファイルの名前を指定する
			comSel = (int)(Math.random() * 3) + 1 ;//相手のじゃんけんぽんも決める。
			comSelStr = RSP.comselName(comSel);//相手が選んだものを見せるために、「comSel」値によってじゃんけんぽんをきめる。
			comFileString = RSP.fileStringCheck(comSel);//「comSel」の値によって、適用するイメージファイルの名前を指定する。
			result = RSP.check(mySel, comSel);じゃんけんぽんの勝負判定をして、「勝利」や「敗北」、「勝負なし」を戻す。
			RSP.WinloseCount(result);//勝つと勝利の回数を、負けると敗北の回数を増やす。
			//各回数を保存するために、Singletonパタンの「RSP」インスタンスで管理する。
		} else if(request.getParameter("ROCK") == "") {
		  //ケンを選んだとき。コードは上記のジャンの場合とほぼ同じ。
			mySel = 2;
			mySelStr = "ケン";
			myFileString = RSP.fileStringCheck(mySel);
			comSel = (int)(Math.random() * 3) + 1 ;
			comSelStr = RSP.comselName(comSel);
			comFileString = RSP.fileStringCheck(comSel);
			result = RSP.check(mySel, comSel);
			RSP.WinloseCount(result);
		} else if(request.getParameter("PAPER") == "") {
		 //ポンを選んだとき。コードは上記のジャンの場合とほぼ同じ。
			mySel = 3;
			mySelStr = "ポン";
			myFileString = RSP.fileStringCheck(mySel);
			comSel = (int)(Math.random() * 3) + 1 ;
			comSelStr = RSP.comselName(comSel);
			comFileString = RSP.fileStringCheck(comSel);
			result = RSP.check(mySel, comSel);
			RSP.WinloseCount(result);
		} else if(request.getParameter("RESET") == "") {
		 //「戦績初期化」ボタンを押す場合に実行。
		 //「RSP」インスタンスに入っている戦績の値を全部0に変える。
			RSP.Reset();
		}
		
		//じゃんけんぽんが終わって、出力するデータをrequestに保存する。
		//私/相手が選んだもの、じゃんけんぽんの結果、選んだものによって適用するファイルネームをでんそうする。
		//戦績のデータは「RSP」インスタンスでアクセスできるので、ここでは送らない。
		request.setAttribute("MYSELSTR", mySelStr);
		request.setAttribute("COMSELSTR", comSelStr);
		request.setAttribute("RESULT", result);
		request.setAttribute("MYFILESTRING", myFileString);
		request.setAttribute("COMFILESTRING", comFileString);
		
		//データと伝送しながら、「"RSPMain.jsp"」に移動する。
		request.getRequestDispatcher("RSPMain.jsp").forward(request, response);
	}

}

RSPMain.jsp
<%@page import="com.inchel.Sep112.main.RSP"%>
<%@page import="com.inchel.Sep112.main.HomeController"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h1 align = "center">★☆★☆★☆じゃんけんーぽい!!ゲーム☆★☆★☆★</h1> <p>

<h2 align = "center">じゃん、けん、ぽんのどっちか1つを選んでください!</h2>

<form action = "HomeController" method = "post">
<!--下の3つのボタンを押すと、「HomeController」SerlvetにPOST方式で移動する。-->
<div align = "center">
	<button name = "SCISSORS"> //このボータンを押すと、「SCISSORS」nameの値を持って「"HomeConstroller"」に移動する。
	//ただし、nullではないただの空っぽの値「""」が入る。
	 <img src = "Scissors.png" width ="200" height = "200">
	 <br> ジャン 
	 </button>
	 
	 <button name = "ROCK"> //このボータンを押すと、「ROCK」nameの値を持って「"HomeConstroller"」に移動する。
	 <img src = "Rock.png" width = "200" height = "200">
	 <br> ケン
	 </button>
	 
	 <button name = "PAPER"> //このボータンを押すと、「PAPER」nameの値を持って「"HomeConstroller"」に移動する。
	 <img src = "Paper.png" width = "200" height = "200">
	 <br> ポン
	 </button>
</div>

	 <p><p><p>
	 
	 <div align = "center">
	 
	 <h1 align = "center"> 結果 </h1>
	 
	 //Singletonインスタンスからも値を受けてみるために、インスタンスの住所を取る。
	 <%RSP rsp = RSP.getInstance();%>
	 
	 //Servletで、選んだじゃんけんぽんによって変わったファイルネームをイメージに適用
	 あなたが出したもの : <%=request.getAttribute("MYSELSTR") %> <br>
	 相手がだしたもの : <%=request.getAttribute("COMSELSTR") %> <br>
	 
	 <br> <img src = "<%=request.getAttribute("MYFILESTRING") %>" width = "300" height = "300"></img> 
	 VS 
	 <img src = "<%=request.getAttribute("COMFILESTRING") %>" width = "300" height = "300"></img>
	 <p>
	 //Servletで実行したじゃんけんぽんの結果と戦績を受けて出力
	 勝負結果 : <%=request.getAttribute("RESULT") %> <br>
	 
	 勝った回数 : <%=rsp.getWinCount()%> <br>
	 負けた回数 : <%=rsp.getLoseCount()%> <br>
	 
	 //RESET機能を実行するため、「RESET」という他のデータを伝送するボタン
	 <button name = "RESET"> 戦績初期化 </button>
	 
	 </div> 
	 </form>

</body>
</html>

最初に出力されるページ(View)と、あのページからどういうふうにデータを送るかが分かったので(Control)、受けたデータを処理する、Modelのコードを下に書く。これはJavaのクラスになっていて、Singletonパタンが適用されている。

RSP.java
package com.inchel.Sep112.main;

public class RSP {
	
	//Singletonパタンでは、インスタンスを1つだけ宣言して、以後のインスタンスを作らない。
	private static final RSP singleRSP = new RSP();
	
	//インスタンスの生成を防ぐため、実行ができないようコンストラクタをprivate属性にする。
	private RSP() {}
	
	//1つだけのインスタンスにアクセスできる、唯一なメソッドを作る。
	//このメソッドはどこでもアクセスできるよう、static属性にする。
	public static RSP getInstance() {
		return singleRSP; //1つだけのインスタンスの住所を戻す。
	}
	
	private int winCount = 0;
	private int loseCount = 0;
	
	public int getWinCount() {
		return winCount;
	}

	public void setWinCount(int winCount) {
		this.winCount = winCount;
	}

	public int getLoseCount() {
		return loseCount;
	}

	public void setLoseCount(int loseCount) {
		this.loseCount = loseCount;
	}

	//受けたデータをもらって、実際じゃんけんぽんをして勝負を決めるメソッド
	public static String check(int mySel, int comSel) {
		//このメソッドで使う値をまとめる。
		// 1: ジャン 2: ケン 3: ポン
		if(mySel == 1) {//私が選んだのが「ジャン」である場合
			if(comSel == 1) return "勝負なし";
			else if(comSel == 2) return "敗北";
			else if(comSel == 3) return "勝利"; 
		} else if(mySel == 2) {//私が選んだのが「ケン」である場合
			if(comSel == 1) return "勝利";
			else if(comSel == 2) return "勝負なし";
			else if(comSel == 3) return "敗北";
		} else if(mySel == 3) { //私が選んだのが「ポン」である場合
			if(comSel == 1) return "敗北";
			else if(comSel == 2) return "勝利";
			else if(comSel == 3) return "勝負なし";
		}
		
		return null;
	}
	
	//ランダムに出た1,2,3,をジャン、ケン、ポンに変換してくれるメソッド
	public static String comselName(int comSel) {
		if(comSel == 1) return "ジャン";
		else if(comSel == 2) return "ケン";
		else if(comSel == 3) return "ポン";
		
		return null;
	}
	
	じゃんけんぽんの結果によって戦績を変えるメソッド
	public static void WinloseCount(String result) {
		
		if(result == "勝利") {
			singleRSP.winCount++;
		} else if(result == "敗北") {
			singleRSP.loseCount++;
		}
		
	}
	
	//私と相手の選んだじゃんけんぽんによって適用するイメージファイルの名前を決めるメソッド
	public static String fileStringCheck(int selNum) {
		
		if(selNum == 1) {
			return "Scissors.png";
		} else if(selNum == 2) {
			return "Rock.png";
		} else if(selNum == 3) {
			return "Paper.png";
		}
		
		return null;
	}
	
	//今までの戦績を全部0に初期化するメソッド
	public static void Reset() {
		singleRSP.winCount = 0;
		singleRSP.loseCount = 0;
		
		System.out.println(singleRSP.winCount);
		System.out.println(singleRSP.loseCount);
	}
	
	
}


以上で、デザインを担当するCSSとデータの妥当性をチェックするJSファイルはない、最小限に作動するコードの作成を完了した。ServletやJSPはITスクールでもずっと学んだり練習したりしているが、MVCやSingletonパタンは扱ったことがあまりなくて、コードが難しくはなかったがコードの配置がむずかしかった。

でも、かなりオブジェクト指向プログラミングにも相応しいし、ちゃんとしたプログラムを作っている気がしておもしろい。今すぐは難しいが、だんだん慣れていけたらいいと思う。

Discussion