2011年5月25日水曜日

太陽電池の製造に太陽電池を

世の中ではいろいろな意味でサンライズにサプライズ?:-)
さて、太陽電池の製造で排出されるCO2に非難の矛先が向かいそうだ。
そこで、太陽電池メーカーは工場の敷地内に自社の太陽電池を設置し、太陽電池製造のエネルギーを自給自足してみたらどうだろう。それができれば自社製品のよい宣伝になる。
いきなり自給率100%でなくてもよい。徐々に上げていけばよい。最初は増産分くらいカバーできるようにしてほしい。

2011年5月8日日曜日

MineSweeper

プログラミングを始める動機の一つにゲーム制作がある。ゲームは技法の宝庫でもあり、教材には適している面がある。しかし、実際に使用されている技法が高度であるほど教材としては不適切になる。初心者のレベルをはるかに超えてしまうからだ。そこで、教材に適したゲームを探した。探してみて意外と少ないので自分で作成することにした。このプログラムは、ゲームとしての面白さより、ゲーム制作のわかりやすさを優先して書いた。
このプログラムにも不備がある。まず、フォントサイズがうち決めされていることと縦方向の中央寄せがいいかげんであることだ。ゲームとしてはスコア計算がない。
また、openZeroは初心者には分かりにくい再帰で書かれている。しかし、これは再起を使えば難しい処理も簡単に表現できる一例になっている。


package game.minesweeper;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

@SuppressWarnings("serial")
public class MineSweeper extends Applet implements MouseListener {
 public static final int N = 8; // board size N x N cells
 public static final int M = 8; // #mines
 public static final int S = 16; // cell size

 // modeling game board
 boolean[][] mines;
 boolean[][] isOpen;
 int[][] counts;
 boolean bang; // game over

 public void init() {
  // データの初期化
  bang = false;
  setMines();
  // GUIの設定
  setFont(new Font("Monospaced",Font.PLAIN,S));
  setSize(N*S+1,N*S+1);
  addMouseListener(this);
 }

 // 地雷の設置
 void setMines() {
  mines = new boolean[N][N];
  isOpen = new boolean[N][N];
  counts = new int[N][N];
  for(int i=0; i<M; i++) {
   int x, y;
   do {
    x = (int)(Math.random() * N);
    y = (int)(Math.random() * N);
   } while(mines[y][x]);
   mines[y][x] = true;
   countMines(x, y);
  }
 }

 // 地雷の場所(x,y)周辺のカウントを増やす
 void countMines(int x, int y) {
  for(int dy=-1; dy<=1; dy++)
   for(int dx=-1; dx<=1; dx++) {
    if (dx==0 && dy==0) continue;
    if (onBoard(x+dx, y+dy))
     counts[y+dy][x+dx]++;
   }
 }

 // viewing model
 public void paint(Graphics g){
  FontMetrics fm = g.getFontMetrics();
  int w = fm.stringWidth("*");
  for(int y=0; y<N; y++)
   for(int x=0; x<N; x++) {
    g.drawRect(x*S, y*S, S, S);
    if (isOpen[y][x]) {
     String s = (mines[y][x]) ? "*" : ""+counts[y][x];
     g.drawString(s,x*S+S/2-w/2,y*S+S-2);
    }
   }
  if (bang) {
   String msg = "Bang!";
   g.setColor(Color.red);
   g.drawString(msg, N*S/2-msg.length()*w/2, N*S/2);
  }
 }

 boolean onBoard(int x, int y) {
  return (0<=y && y<N && 0<=x && x<N);
 }

 // すべて開く
 void openAll() {
  for(int y=0; y<N; y++)
   for(int x=0; x<N; x++)
    isOpen[y][x] = true;
 }

 // 隣接する0をすべて開ける
 void openZero(int x, int y) {
  if (! onBoard(x, y)) return;
  if (isOpen[y][x]) return;
  isOpen[y][x] = true;
  if (counts[y][x] > 0) return;
  for(int dy=-1; dy<=1; dy++)
   for(int dx=-1; dx<=1; dx++)
    openZero(x+dx, y+dy);
 }

 @Override
 public void mouseClicked(MouseEvent e) {
  int x = e.getX() / S;
  int y = e.getY() / S;
  if (! onBoard(x, y)) return;
  if (mines[y][x]) {
   bang = true;
   openAll();
  }
  openZero(x, y);
  repaint();
 }

 @Override
 public void mousePressed(MouseEvent e) {}

 @Override
 public void mouseReleased(MouseEvent e) {}

 @Override
 public void mouseEntered(MouseEvent e) {}

 @Override
 public void mouseExited(MouseEvent e) {}
}

電子ブックは横書きが良い

電子ブックは読みたいときに読めることが利点だ。それにはiPadよりiPhoneの方がよい。しかし、iPhoneは画面が小さい。これを解消するには画面を横向きにすることだ。そうすると横書き文書の文字をそこそこ拡大して読むことができる。
これだ縦書きではうまくいかない。つまりページのレイアウトで短い方の辺を拡大できることに意味がある。よって電子ブック時代はページ内の文字数を少なくするか、さもなければ横書きにすることだ。