This seems to work acceptably. It will ask you if one of the buffers on the kill list has unsaved changes.
(defun close-all-other-buffers-and-frames ()
"Destroy all frames except this one, kill all buffers, display `*scratch*'."
(interactive)
(set-buffer "*scratch*")
(delete-other-frames)
(let ((l (buffer-list)) b)
(while l
(setq b (car l)
l (cdr l) )
(and (buffer-file-name b)
(kill-buffer b) ) ) ) )
I have a feeling the loop to kill buffers could be done more elegantly -- please suggest improvements!