//プログラム s8100032 神谷
//修正
//テトリスもどき ゲーム
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.awt.event.KeyEvent;
/*
*/
//スレッドとキー入力を利用する
public class tetoris extends Applet implements Runnable,KeyListener {
boolean isStandalone = false;
//引数値の取得
public String getParameter(String key, String def) {
return isStandalone ? System.getProperty(key, def) :
(getParameter(key) != null ? getParameter(key) : def);
}
Thread w_clock = null; //スレッド
Image image1;//ダブルバッファ
Graphics offgraphics;
int area[][] = new int [14][24]; //ピース記憶領域
int piece[][] = new int [5][5]; //ブロック生成領域
boolean start_check = false;
boolean loop_check = false;
boolean replay_check = true;
boolean level_check = true;
int bx,by; //落下中のピースの座標
int bp; //生成ピースの番号
int nline; //消したラインの総数
int nscore; //現在のスコア
int nlevel; //現在のレヴェル
int nfast=500;
//アプレットの初期化
public void init() {
///キー入力大作戦
addKeyListener(this);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}//init
//コンポーネントの初期化
private void jbInit() throws Exception {
this.setBackground(Color.black);//背景色を黒に
this.setForeground(Color.white);
}//jbinit
//関数の定義が必要
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
//キーが押されたらキーイベントで呼び出される
public void keyPressed(KeyEvent e){
if(!start_check){
if(e.getKeyCode() == KeyEvent.VK_S){//'s'(開始(start)キー)
start_check = true;
Set_Init();
Game_Start();
}//if keyEvent s
}//if start_check
else if(!replay_check){
if(e.getKeyCode() == KeyEvent.VK_S){
replay_check = true;
Set_Init();
loop_check = false;
}//if keyEvent s
}//if replay_check
else /*if(level_check)*/{
switch(e.getKeyCode()) {
case KeyEvent.VK_DOWN://方向キー
Move_Down();//下移動
break;
case KeyEvent.VK_RIGHT:
Move_Right();//右移動 ??
break;
case KeyEvent.VK_LEFT:
Move_Left();
break;
case KeyEvent.VK_SPACE://空白キー
Roll_piece();//回転 ??
}//switch
}//else
repaint();//再描画;
}//keypress
//////////////////////////////////////////////////////////////////////////////
////// 初期化 //////
//////////////////////////////////////////////////////////////////////////////
public void Set_Init(){//初期化
int i,j;
bx = 7;
by = 2;
nline = 0;
nscore = 0;
nlevel = 1;
nfast = 500;
///フィールドの初期化
/// 0 :ピースが存在しない、-1 :壁
for(i=2;i<12;i++)
for(j=0;j<22;j++)
area[i][j] = 0;
for(i=1;i<13;i+=11)//左右の壁
for(j=0;j<22;j++)
area[i][j] = -1;
for(i=2;i<12;i++){//下の壁
area[i][22] = -1;
area[i][23] = -1;
}
//最初のピースの生成
Create_piece();
}//set init
///////////////////////////////////////////////////////////////////////////////
////// ピースの描画 //////
//////////////////////////////////////////////////////////////////////////////
public void paint (Graphics g)//表示
{
Graphics graphics = offgraphics;
int i,j;
//消去
graphics.clearRect(0,0, getWidth() , getHeight());//??
graphics.setColor(Color.darkGray);
graphics.fillRect(99,19,151,301);
//フィールドに落下したピースを表示
for(i=2;i<12;i++){
for(j=2;j<22;j++){
if(area[i][j] >= 1){
graphics.setColor(new Color(100+area[i][j]*22,
150+area[i][j]%2*70,80+(7-area[i][j])*25));//ピースの番号から色を作成
graphics.fillRect(100+(i-2)*15,20+(j-2)*15,14,14);
}
else if(area[i][j] == -5){//ゲーム終了時
graphics.setColor(Color.gray);
graphics.fillRect(100+(i-2)*15,20+(j-2)*15,14,14);
}
else{
graphics.setColor(new Color(0,0,0));//黒を指定
graphics.fillRect(100+(i-2)*15,20+(j-2)*15,14,14);
}
}
}
//落下中のピースを表示
for(i=0;i<5;i++){
for(j=0;j<5;j++){
if(piece[i][j] >= 1){
graphics.setColor(new Color(100+piece[i][j]*22,
150+piece[i][j]%2*70,80+(7-piece[i][j])*25));
graphics.fillRect(100 + (i + bx - 4) * 15,20 + (j + by - 4) * 15,14,14);
}
}
}
//文字フォントを設定
graphics.setFont(new Font("MS Gothic",Font.PLAIN,12));
graphics.setColor(Color.white);
graphics.drawString("Score",20,50);
graphics.drawString(Integer.toString(nscore),40,89);
graphics.drawString("Level",20,140);
graphics.drawString(Integer.toString(nlevel),40,179);
graphics.drawString("Line",25,230);
graphics.drawString(Integer.toString(nline),40,269);
if(!level_check){
level_check = true;
graphics.drawString("Level up!!",110,165);
}//if level_chck
if(!start_check){
graphics.drawString("Press 'S' key !!",110,165);
}//if
if(!replay_check){
graphics.drawString("Game over",140,155);
graphics.drawString("press 's'key.",90,171);
}//if
g.drawImage(image1,0,0,this);
}//paint
//////////////////////////////////////////////////////////////////////////////
////// スレッド実働部 //////
////// ゲームオーバーの判定など… //////
//////////////////////////////////////////////////////////////////////////////
public void run() {
int i,j,count;
while (true) {
if(!loop_check){
count = 0;
//ピースをひとつ下に落下が可能かどうか?
for(i=0;i<5;i++)//背景が0のダイスの数
for(j=0;j<5;j++)
if(piece[i][j] >= 1 && area[bx + i - 2][by + j - 1] == 0)count++;
if(count!=4){//ピースの落下は不可
//ピースをフィールドにおく
for(i=0;i<5;i++)
for(j=0;j<5;j++)
if(piece[i][j] >= 1)area[bx + i - 2][by + j - 2] = piece[i][j];//
CheckClear();//行が消せるかどうか判定/処理する関数を呼ぶ;??
if(area[7][2]>=1){//ゲームオーバー
loop_check = true;
Game_Over();
replay_check = false;
}//if game over
//次のピースを準備
bx=7;
by=2;
Create_piece(); //*ピースを生成する関数を呼ぶ; ??
}//if count not4
else by++;
}//if loop_check
///再描画
repaint();
try
{
Thread.sleep(nfast);//nfast時間休止
}//try
catch(Exception e) {}//catch
}//while
}//run
/////////////////////////////////////////////////////
////// ダブルバッファ //////
//////////////////////////////////////////////////////
public void update(Graphics g) {
//g.clipRect(5,5,95,95);
paint(g);
}//update
/////////////////////////////////////////////////////////////
////// ピースを生成する //////
/////////////////////////////////////////////////////////////
public void Create_piece(){
int i,j;
///ピース生成領域の初期化
for(i=0;i<5;i++)
for(j=0;j<5;j++)
piece[i][j] = 0;
///乱数( bp )よりピースを生成
bp = (int)(Math.random() * 100000 ) % 7 + 1;
switch(bp){
case 1:
piece[1][1] = bp;
piece[1][2] = bp;
break;
case 2:
piece[3][1] = bp;
piece[3][2] = bp;
break;
case 3:
piece[1][2] = bp;
piece[1][3] = bp;
break;
case 4:
piece[2][1] = bp;
piece[3][3] = bp;
break;
case 5:
piece[2][1] = bp;
piece[1][3] = bp;
break;
case 6:
piece[1][3] = bp;
piece[3][3] = bp;
break;
case 7://I 型ピース
piece[2][1] = bp;
piece[2][4] = bp;//??
break;
}//switch
piece[2][2] = bp;
piece[2][3] = bp;
}//create_piece
///////////////////////////////////////////////////////////////////////
////// ピースを下に移動する //////
///////////////////////////////////////////////////////////////////////
public void Move_Down(){
int i,j,count;
count = 0;
///移動可能か判定
for(i=0;i<5;i++)
for(j=0;j<5;j++)
if(piece[i][j] >= 1 && area[bx + i - 2][by + j - 1] == 0)count++;
if(count == 4){///移動可
by++;
nscore += nlevel;
}//if
repaint();
}//movedown
/////////////////////////////////////////////////////////////
////// ピースを右に移動する //////
/////////////////////////////////////////////////////////////
public void Move_Right(){
int i,j,count;
count = 0;
///移動可能か判定
for(i=0;i<5;i++)
for(j=0;j<5;j++)
if(piece[i][j] >= 1 && area[bx + i - 1][by + j - 2] == 0)count++;
///可能ならば移動
if(count == 4)bx++;
repaint();
}//move right
/////////////////////////////////////////////////////////////////
////// ピースを左に移動する //////
/////////////////////////////////////////////////////////////////
public void Move_Left(){
int i,j,count;
count = 0;
///移動可能か判定
for(i=0;i<5;i++)
for(j=0;j<5;j++)
if(piece[i][j] >= 1 && area[bx + i - 3][by + j - 2] == 0)count++;
///可能ならば移動
if(count == 4)bx--;
repaint();
}//move left
//////////////////////////////////////////////////////////////
////// ピースを回転する //////
/////////////////////////////////////////////////////////////
public void Roll_piece(){
int i,j,count;
int copy_piece[][] = new int[5][5];//*配列の領域を確保; ??
count = 0;
///仮回転体生成
for(i=0;i<5;i++)
for(j=0;j<5;j++)
//copy_piece[i][j] = piece[?? - j][i];//??
copy_piece[4-j][i] = piece[i][j];
///仮回転体を使用して回転可能か判定
for(i=0;i<5;i++)
for(j=0;j<5;j++)
if(copy_piece[i][j] >= 1 && area[bx + i - 2][by + j - 2] == 0)count++;
///回転可能なら回転する
if(count == 4){
///生成したピースを回転後の形に更新
for(i=0;i<5;i++)
for(j=0;j<5;j++)
piece[i][j] = copy_piece[i][j];
repaint();
}//if
}//roll piece
////////////////////////////////////////////////////////////////////
////// ラインが消せるかどうかを判定後クリア //////
////////////////////////////////////////////////////////////////////
public void CheckClear(){
///ピースが消えるかどうかを判定・ピースの消去
int i,j,s,k;
int ld; //ラインが消せるかどうか判定する
int flg=0; //ライン消したかどうか確認する
int hline;
int linecount=0; //一度に消した行数
int bonus=1; //スコア計算用
hline = nline/10;
//ラインが消せるかどうか判定
for(i=21;i>0;i--){
///ラインが消せるかどうか判定
ld=1;
for(j=2;j<12;j++)ld = ld * area[j][i];
if(ld!=0){ //一列消した!!
//ラインが消去可能ならば上からプレスする
for(k=i-1;k>0;k--)
for(s=2;s<12;s++)area[s][k+1]=area[s][k];
flg=1;
i++;
nline++;//累積行数
linecount++;
}//if
}//for
//一列でも消していたら…
if(flg==1){
///スコアの計算
for(i=1;i10 ){//10段消すと
nlevel++; //レベルアップ!!
level_check = false;
nfast-=40; //早く落ちます
if(nfast<=70)nfast=120; //最小120
}//if
repaint();
}//if flag1
}//checkclear
////////////////////////////////////////////////////////////////
////// [s]キーが押されたときの処理 //////
/////////////////////////////////////////////////////////////////
void Game_Start(){
w_clock = new Thread(this);
w_clock.start();
}//game start
public void start(){
///ダブルバッファ
image1 = createImage(this.getSize().width ,this.getSize().height);
offgraphics = image1.getGraphics();
Set_Init();
}//start
////////////////////////////////////////////////////////////////
////// ゲームオーバー時の処理 //////
////////////////////////////////////////////////////////////////
void Game_Over(){
int i,j;
for(j=22;j>1;j--){
for(i=2;i<12;i++)
if(area[i][j] >= 1)area[i][j] = -5;
repaint();
}//for
}//game over
}//tetoris